package models

import (
	"fmt"

	"odoo-go/pkg/orm"
)

// initCrmAnalysis registers the crm.lead.analysis transient model
// for pipeline reporting and dashboard data.
// Mirrors: odoo/addons/crm/report/crm_activity_report.py (simplified)
func initCrmAnalysis() {
	m := orm.NewModel("crm.lead.analysis", orm.ModelOpts{
		Description: "Pipeline Analysis",
		Type:        orm.ModelTransient,
	})

	m.AddFields(
		orm.Many2one("team_id", "crm.team", orm.FieldOpts{
			String: "Sales Team",
			Help:   "Filter analysis by sales team.",
		}),
		orm.Many2one("user_id", "res.users", orm.FieldOpts{
			String: "Salesperson",
			Help:   "Filter analysis by salesperson.",
		}),
		orm.Date("date_from", orm.FieldOpts{
			String: "From",
			Help:   "Start date for the analysis period.",
		}),
		orm.Date("date_to", orm.FieldOpts{
			String: "To",
			Help:   "End date for the analysis period.",
		}),
		orm.Many2one("company_id", "res.company", orm.FieldOpts{
			String: "Company",
			Help:   "Filter analysis by company.",
		}),
	)

	// get_pipeline_data: return pipeline statistics grouped by stage.
	// Mirrors: odoo/addons/crm/report/crm_activity_report.py read_group
	m.RegisterMethod("get_pipeline_data", func(rs *orm.Recordset, args ...interface{}) (interface{}, error) {
		env := rs.Env()

		// Pipeline by stage
		rows, err := env.Tx().Query(env.Ctx(), `
			SELECT s.name, COUNT(l.id), COALESCE(SUM(l.expected_revenue::float8), 0)
			FROM crm_lead l
			JOIN crm_stage s ON s.id = l.stage_id
			WHERE l.active = true AND l.type = 'opportunity'
			GROUP BY s.id, s.name, s.sequence
			ORDER BY s.sequence`)
		if err != nil {
			return nil, fmt.Errorf("get_pipeline_data: stages query: %w", err)
		}
		defer rows.Close()

		var stages []map[string]interface{}
		for rows.Next() {
			var name string
			var count int64
			var revenue float64
			if err := rows.Scan(&name, &count, &revenue); err != nil {
				return nil, fmt.Errorf("get_pipeline_data: scan stage: %w", err)
			}
			stages = append(stages, map[string]interface{}{
				"stage":   name,
				"count":   count,
				"revenue": revenue,
			})
		}

		// Win rate
		var total, won int64
		_ = env.Tx().QueryRow(env.Ctx(),
			`SELECT COUNT(*), COALESCE(SUM(CASE WHEN s.is_won THEN 1 ELSE 0 END), 0)
			 FROM crm_lead l
			 JOIN crm_stage s ON s.id = l.stage_id
			 WHERE l.type = 'opportunity'`,
		).Scan(&total, &won)

		winRate := float64(0)
		if total > 0 {
			winRate = float64(won) / float64(total) * 100
		}

		return map[string]interface{}{
			"stages":   stages,
			"total":    total,
			"won":      won,
			"win_rate": winRate,
		}, nil
	})

	// get_conversion_data: return lead-to-opportunity conversion statistics.
	// Mirrors: odoo/addons/crm/report/crm_activity_report.py (conversion metrics)
	m.RegisterMethod("get_conversion_data", func(rs *orm.Recordset, args ...interface{}) (interface{}, error) {
		env := rs.Env()

		var totalLeads, convertedLeads int64
		_ = env.Tx().QueryRow(env.Ctx(), `
			SELECT
				COUNT(*) FILTER (WHERE type = 'lead'),
				COUNT(*) FILTER (WHERE type = 'opportunity' AND date_conversion IS NOT NULL)
			FROM crm_lead WHERE active = true`,
		).Scan(&totalLeads, &convertedLeads)

		conversionRate := float64(0)
		if totalLeads > 0 {
			conversionRate = float64(convertedLeads) / float64(totalLeads) * 100
		}

		// Average days to convert
		var avgDaysConvert float64
		_ = env.Tx().QueryRow(env.Ctx(), `
			SELECT COALESCE(AVG(EXTRACT(EPOCH FROM (date_conversion - create_date)) / 86400), 0)
			FROM crm_lead
			WHERE type = 'opportunity' AND date_conversion IS NOT NULL AND active = true`,
		).Scan(&avgDaysConvert)

		// Average days to close (won)
		var avgDaysClose float64
		_ = env.Tx().QueryRow(env.Ctx(), `
			SELECT COALESCE(AVG(EXTRACT(EPOCH FROM (date_closed - create_date)) / 86400), 0)
			FROM crm_lead
			WHERE state = 'won' AND date_closed IS NOT NULL`,
		).Scan(&avgDaysClose)

		return map[string]interface{}{
			"total_leads":      totalLeads,
			"converted_leads":  convertedLeads,
			"conversion_rate":  conversionRate,
			"avg_days_convert": avgDaysConvert,
			"avg_days_close":   avgDaysClose,
		}, nil
	})

	// get_team_performance: return per-team performance comparison.
	// Mirrors: odoo/addons/crm/report/crm_activity_report.py (team grouping)
	m.RegisterMethod("get_team_performance", func(rs *orm.Recordset, args ...interface{}) (interface{}, error) {
		env := rs.Env()

		rows, err := env.Tx().Query(env.Ctx(), `
			SELECT
				t.name,
				COUNT(l.id) AS opp_count,
				COALESCE(SUM(l.expected_revenue::float8), 0) AS total_revenue,
				COALESCE(AVG(l.probability), 0) AS avg_probability,
				COUNT(l.id) FILTER (WHERE l.state = 'won') AS won_count
			FROM crm_lead l
			JOIN crm_team t ON t.id = l.team_id
			WHERE l.active = true AND l.type = 'opportunity'
			GROUP BY t.id, t.name
			ORDER BY total_revenue DESC`)
		if err != nil {
			return nil, fmt.Errorf("get_team_performance: %w", err)
		}
		defer rows.Close()

		var teams []map[string]interface{}
		for rows.Next() {
			var name string
			var oppCount, wonCount int64
			var totalRevenue, avgProb float64
			if err := rows.Scan(&name, &oppCount, &totalRevenue, &avgProb, &wonCount); err != nil {
				return nil, fmt.Errorf("get_team_performance: scan: %w", err)
			}
			winRate := float64(0)
			if oppCount > 0 {
				winRate = float64(wonCount) / float64(oppCount) * 100
			}
			teams = append(teams, map[string]interface{}{
				"team":            name,
				"opportunities":   oppCount,
				"revenue":         totalRevenue,
				"avg_probability": avgProb,
				"won":             wonCount,
				"win_rate":        winRate,
			})
		}

		return map[string]interface{}{"teams": teams}, nil
	})

	// get_salesperson_performance: return per-salesperson performance data.
	// Mirrors: odoo/addons/crm/report/crm_activity_report.py (user grouping)
	m.RegisterMethod("get_salesperson_performance", func(rs *orm.Recordset, args ...interface{}) (interface{}, error) {
		env := rs.Env()

		rows, err := env.Tx().Query(env.Ctx(), `
			SELECT
				u.login,
				COUNT(l.id) AS opp_count,
				COALESCE(SUM(l.expected_revenue::float8), 0) AS total_revenue,
				COUNT(l.id) FILTER (WHERE l.state = 'won') AS won_count,
				COUNT(l.id) FILTER (WHERE l.state = 'lost') AS lost_count
			FROM crm_lead l
			JOIN res_users u ON u.id = l.user_id
			WHERE l.active = true AND l.type = 'opportunity'
			GROUP BY u.id, u.login
			ORDER BY total_revenue DESC`)
		if err != nil {
			return nil, fmt.Errorf("get_salesperson_performance: %w", err)
		}
		defer rows.Close()

		var users []map[string]interface{}
		for rows.Next() {
			var login string
			var oppCount, wonCount, lostCount int64
			var totalRevenue float64
			if err := rows.Scan(&login, &oppCount, &totalRevenue, &wonCount, &lostCount); err != nil {
				return nil, fmt.Errorf("get_salesperson_performance: scan: %w", err)
			}
			winRate := float64(0)
			if oppCount > 0 {
				winRate = float64(wonCount) / float64(oppCount) * 100
			}
			users = append(users, map[string]interface{}{
				"salesperson": login,
				"opportunities": oppCount,
				"revenue":       totalRevenue,
				"won":           wonCount,
				"lost":          lostCount,
				"win_rate":      winRate,
			})
		}

		return map[string]interface{}{"salespersons": users}, nil
	})
}
