import pool from "../config/db";
import { RowDataPacket } from "mysql2";
import { Property } from "../types/property";
import { PriceHistoryModel } from "../models/priceHistoryModel";

/**
 * ScoringService — Algoritmo de puntuación 0–10 para propiedades.
 *
 * Factores:
 *  - Precio/m² (comparado con la media del municipio)  → hasta 3 puntos
 *  - Habitaciones                                       → hasta 2 puntos
 *  - Superficie                                         → hasta 1.5 puntos
 *  - Tendencia de precio (bajada = mejor)               → hasta 1.5 puntos
 *  - Tiene imagen                                       → 0.5 puntos
 *  - Tiene descripción / URL                            → 0.5 puntos
 * Total máximo = 10
 */
export class ScoringService {
    /** Calcula y guarda el score de una propiedad por su ID */
    async scoreProperty(property: Property & { id?: number }): Promise<number> {
        let score = 0;

        // 1. Precio por m² (hasta 3 pts)
        if (property.size_m2 && property.size_m2 > 0 && property.price > 0) {
            const pm2 = property.price / property.size_m2;
            const avgPm2 = await this.getAvgPricePerM2(property.municipality || "Lliria");
            if (avgPm2 > 0) {
                const ratio = pm2 / avgPm2;
                if (ratio <= 0.7) score += 3;
                else if (ratio <= 0.85) score += 2.5;
                else if (ratio <= 0.95) score += 2;
                else if (ratio <= 1.05) score += 1.5;
                else if (ratio <= 1.2) score += 1;
                else score += 0.3;
            } else {
                score += 1.5; // sin datos de referencia → score neutro
            }
        }

        // 2. Habitaciones (hasta 2 pts)
        const rooms = property.rooms || 0;
        if (rooms >= 4) score += 2;
        else if (rooms === 3) score += 1.7;
        else if (rooms === 2) score += 1.3;
        else if (rooms === 1) score += 0.7;
        // 0 habitaciones → 0 pts

        // 3. Superficie (hasta 1.5 pts)
        const m2 = property.size_m2 || 0;
        if (m2 >= 150) score += 1.5;
        else if (m2 >= 100) score += 1.2;
        else if (m2 >= 70) score += 0.9;
        else if (m2 >= 50) score += 0.5;

        // 4. Tendencia de precio (hasta 1.5 pts)
        if (property.id) {
            const history = await PriceHistoryModel.getByProperty(property.id);
            if (history.length >= 2) {
                const firstPrice = Number(history[0].price);
                const lastPrice = Number(history[history.length - 1].price);
                const change = (lastPrice - firstPrice) / firstPrice;
                if (change <= -0.1) score += 1.5;  // bajó ≥10%
                else if (change < -0.05) score += 1.0; // bajó 5-10%
                else if (change < 0) score += 0.5;    // bajó algo
                else if (change > 0.05) score -= 0.5; // subió → penalización
            }
        }

        // 5. Tiene imagen (0.5 pts)
        if (property.image_url) score += 0.5;

        // 6. Tiene URL (0.5 pts)
        if (property.url && property.url.startsWith("http")) score += 0.5;

        const finalScore = Math.max(0, Math.min(10, Math.round(score * 100) / 100));

        // Guardar score y price_per_m2 en BD
        if (property.id) {
            const pm2 = property.price > 0 && (property.size_m2 || 0) > 0
                ? Math.round(property.price / property.size_m2!)
                : null;
            await pool.query(
                `UPDATE properties SET score = ?, price_per_m2 = ? WHERE id = ?`,
                [finalScore, pm2, property.id]
            );
        }

        return finalScore;
    }

    /** Re-puntúa todas las propiedades */
    async scoreAll(): Promise<number> {
        const [rows] = await pool.query<RowDataPacket[]>(
            `SELECT id, price, size_m2, rooms, municipality, image_url, url, source FROM properties WHERE is_duplicate = 0 OR is_duplicate IS NULL`
        );
        let count = 0;
        for (const row of rows) {
            await this.scoreProperty(row as Property & { id: number });
            count++;
        }
        console.log(`[ScoringService] ${count} propiedades puntuadas`);
        return count;
    }

    private async getAvgPricePerM2(municipality: string): Promise<number> {
        const [rows] = await pool.query<RowDataPacket[]>(
            `SELECT AVG(price / NULLIF(size_m2, 0)) AS avg_pm2
       FROM properties
       WHERE municipality LIKE ? AND size_m2 > 0 AND price > 0 AND is_duplicate = 0`,
            [`%${municipality}%`]
        );
        return Number(rows[0]?.avg_pm2) || 0;
    }
}
