import { Request, Response } from "express";
import { PropertyService } from "../services/propertyService";
import { PropertyModel } from "../models/propertyModel";
import { PriceHistoryModel } from "../models/priceHistoryModel";

const service = new PropertyService();

export const propertyController = {
  getAll: async (req: Request, res: Response): Promise<void> => {
    try {
      const { municipality, property_type, min_price, max_price, min_rooms, page, per_page, search, operation_type, valencia_zone } = req.query as any;

      // Si se piden datos paginados via API
      if (page) {
        const result = await PropertyModel.findPaginated(
          Number(page) || 1,
          Number(per_page) || 50,
          search || undefined
        );
        res.json({ success: true, data: result.rows, count: result.rows.length, total: result.total });
        return;
      }

      const props = await PropertyModel.filterAdvanced(
        min_price ? Number(min_price) : undefined,
        max_price ? Number(max_price) : undefined,
        property_type || undefined,
        municipality || undefined,
        min_rooms ? Number(min_rooms) : undefined,
        undefined,
        operation_type === "rent" ? "rent" : operation_type === "sale" ? "sale" : undefined,
        valencia_zone || undefined
      );
      res.json({ success: true, data: props, count: props.length });
    } catch (err) {
      res.status(500).json({ success: false, error: "Error al obtener propiedades" });
    }
  },

  /**
   * DataTables server-side endpoint.
   * GET /api/properties/dt?draw=N&start=N&length=N&search[value]=X&order[0][column]=N&order[0][dir]=asc
   * Filtros adicionales: f_muni, f_tipo, f_pmin, f_pmax, f_rooms, f_portal, f_deleted
   */
  getDataTable: async (req: Request, res: Response): Promise<void> => {
    try {
      const q = req.query as any;
      const draw = parseInt(q.draw || q["draw"]) || 1;
      const start = parseInt(q.start || q["start"]) || 0;
      const length = parseInt(q.length || q["length"]) || 100;
      const search = (q["search[value]"] || "").trim();
      const orderCol = parseInt(q["order[0][column]"] ?? "2");
      const orderDir = (q["order[0][dir]"] === "desc" ? "desc" : "asc") as "asc" | "desc";

      const result = await PropertyModel.findPaginatedDT({
        draw, start, length, search,
        orderCol, orderDir,
        municipality: q.f_muni || undefined,
        property_type: q.f_tipo || undefined,
        min_price: q.f_op === "rent" ? undefined : (q.f_pmin ? Number(q.f_pmin) : undefined),
        max_price: q.f_pmax ? Number(q.f_pmax) : undefined,
        min_rooms: q.f_rooms ? Number(q.f_rooms) : undefined,
        source: q.f_portal || undefined,
        deleted: q.f_deleted === "1",
        operation_type: q.f_op === "rent" ? "rent" : q.f_op === "sale" ? "sale" : undefined,
        valencia_zone: q.f_valencia_zone || undefined,
        userId: Number((req.session as any).userId),
      });

      res.json(result);
    } catch (err) {
      res.status(500).json({ draw: 1, recordsTotal: 0, recordsFiltered: 0, data: [], error: "Error al obtener datos" });
    }
  },

  getById: async (req: Request, res: Response): Promise<void> => {
    try {
      const prop = await PropertyModel.findById(parseInt(req.params.id), Number((req.session as any).userId));
      if (!prop) { res.status(404).json({ success: false, error: "No encontrada" }); return; }
      res.json({ success: true, data: prop });
    } catch (err) {
      res.status(500).json({ success: false, error: "Error" });
    }
  },

  delete: async (req: Request, res: Response): Promise<void> => {
    try {
      await PropertyModel.deleteById(parseInt(req.params.id));
      res.json({ success: true });
    } catch (err) {
      res.status(500).json({ success: false, error: "Error al eliminar" });
    }
  },

  restore: async (req: Request, res: Response): Promise<void> => {
    try {
      await PropertyModel.restoreById(parseInt(req.params.id));
      res.json({ success: true });
    } catch (err) {
      res.status(500).json({ success: false, error: "Error al restaurar" });
    }
  },

  hardDelete: async (req: Request, res: Response): Promise<void> => {
    try {
      await PropertyModel.hardDeleteById(parseInt(req.params.id));
      res.json({ success: true });
    } catch (err) {
      res.status(500).json({ success: false, error: "Error al eliminar definitivamente" });
    }
  },

  toggleFavorite: async (req: Request, res: Response): Promise<void> => {
    try {
      const id = parseInt(req.params.id);
      const isFav = await PropertyModel.toggleFavorite(id, Number((req.session as any).userId));
      res.json({ success: true, is_favorite: isFav });
    } catch (err) {
      res.status(500).json({ success: false, error: "Error al actualizar favorito" });
    }
  },

  updateNotes: async (req: Request, res: Response): Promise<void> => {
    try {
      const id = parseInt(req.params.id);
      const { notes } = req.body;
      await PropertyModel.updateNotes(id, Number((req.session as any).userId), notes || "");
      res.json({ success: true });
    } catch (err) {
      res.status(500).json({ success: false, error: "Error al guardar notas" });
    }
  },

  getFavorites: async (req: Request, res: Response): Promise<void> => {
    try {
      const favs = await PropertyModel.findFavorites(Number((req.session as any).userId));
      res.json({ success: true, data: favs, count: favs.length });
    } catch (err) {
      res.status(500).json({ success: false, error: "Error al obtener favoritos" });
    }
  },

  getPriceHistory: async (req: Request, res: Response): Promise<void> => {
    try {
      const id = parseInt(req.params.id);
      const history = await PriceHistoryModel.getByProperty(id);
      res.json({ success: true, data: history });
    } catch (err) {
      res.status(500).json({ success: false, error: "Error al obtener historial" });
    }
  },
};

export default propertyController;
