import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod/v3';
import type { ReportsDeps } from '../shared/types';

const REPORT_TYPES = [
  'market_overview',
  'district_analysis',
  'industrial_zone',
  'investment_feasibility',
  'price_forecast',
] as const;

const PROPERTY_TYPES = ['apartment', 'house', 'townhouse', 'villa', 'land', 'shophouse', 'industrial'] as const;

const MACRO_DATA_CATEGORIES = [
  'gdp',
  'population',
  'fdi',
  'infrastructure',
  'real_estate_index',
  'construction_permits',
  'urbanization',
] as const;

const GenerateReportSchema = {
  reportType: z.enum(REPORT_TYPES).describe('Type of report to generate'),
  location: z.string().describe('City, district, or province for the report'),
  propertyType: z.enum(PROPERTY_TYPES).optional().describe('Filter by property type'),
  period: z.enum(['1m', '3m', '6m', '1y', '2y', '5y']).default('1y').describe('Time period for data analysis'),
  includeForecasts: z.boolean().default(false).describe('Include price/demand forecasts'),
  includeMacro: z.boolean().default(false).describe('Include macro-economic data in the report'),
  language: z.enum(['vi', 'en']).default('vi').describe('Report language'),
};

const GetMacroDataSchema = {
  province: z.string().describe('Province name (e.g. "Bình Dương", "Hồ Chí Minh")'),
  categories: z.array(z.enum(MACRO_DATA_CATEGORIES)).min(1).describe('Data categories to retrieve'),
  fromYear: z.number().int().min(2010).default(2020).describe('Start year'),
  toYear: z.number().int().max(2030).default(2025).describe('End year'),
};

export function createReportsServer(deps: ReportsDeps): McpServer {
  const baseUrl = deps.apiBaseUrl.replace(/\/$/, '');

  const server = new McpServer({
    name: 'goodgo-reports',
    version: '0.1.0',
  });

  server.tool(
    'generate_report',
    'Generate a comprehensive real estate market report for a given location and property type.',
    GenerateReportSchema,
    async (params: z.infer<z.ZodObject<typeof GenerateReportSchema>>) => {
      const response = await fetch(`${baseUrl}/reports/generate`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          report_type: params.reportType,
          location: params.location,
          property_type: params.propertyType ?? null,
          period: params.period,
          include_forecasts: params.includeForecasts,
          include_macro: params.includeMacro,
          language: params.language,
        }),
      });

      if (!response.ok) {
        const errorText = await response.text();
        return {
          content: [{
            type: 'text' as const,
            text: JSON.stringify({ error: `Report generation error (${response.status}): ${errorText}` }),
          }],
          isError: true,
        };
      }

      const data = (await response.json()) as GeneratedReport;

      return {
        content: [{
          type: 'text' as const,
          text: JSON.stringify({
            reportId: data.report_id,
            reportType: data.report_type,
            title: data.title,
            location: data.location,
            generatedAt: data.generated_at,
            summary: data.summary,
            sections: (data.sections ?? []).map((s) => ({
              title: s.title,
              content: s.content,
              charts: s.charts ?? [],
            })),
            keyMetrics: data.key_metrics ?? {},
            forecasts: data.forecasts ?? null,
            macroData: data.macro_data ?? null,
          }, null, 2),
        }],
      };
    },
  );

  server.tool(
    'get_macro_data',
    'Retrieve macro-economic data (GDP, population, FDI, infrastructure) for a Vietnamese province.',
    GetMacroDataSchema,
    async (params: z.infer<z.ZodObject<typeof GetMacroDataSchema>>) => {
      const qs = new URLSearchParams();
      qs.set('province', params.province);
      for (const cat of params.categories) qs.append('categories', cat);
      qs.set('fromYear', String(params.fromYear));
      qs.set('toYear', String(params.toYear));

      const response = await fetch(`${baseUrl}/reports/macro-data?${qs.toString()}`, {
        method: 'GET',
        headers: { 'Content-Type': 'application/json' },
      });

      if (!response.ok) {
        const errorText = await response.text();
        return {
          content: [{
            type: 'text' as const,
            text: JSON.stringify({ error: `Macro data error (${response.status}): ${errorText}` }),
          }],
          isError: true,
        };
      }

      const data = (await response.json()) as MacroDataResponse;

      return {
        content: [{
          type: 'text' as const,
          text: JSON.stringify({
            province: data.province,
            period: { from: params.fromYear, to: params.toYear },
            data: Object.fromEntries(
              Object.entries(data.data ?? {}).map(([category, series]) => [
                category,
                (series as MacroDataPoint[]).map((point) => ({
                  year: point.year,
                  value: point.value,
                  unit: point.unit,
                  yoyChange: point.yoy_change ?? null,
                })),
              ]),
            ),
            highlights: data.highlights ?? [],
          }, null, 2),
        }],
      };
    },
  );

  return server;
}

// Response types from the AI service
interface GeneratedReport {
  report_id: string;
  report_type: string;
  title: string;
  location: string;
  generated_at: string;
  summary: string;
  sections?: {
    title: string;
    content: string;
    charts?: { type: string; title: string; data: unknown }[];
  }[];
  key_metrics?: Record<string, unknown>;
  forecasts?: {
    price_trend: { period: string; predicted_change_pct: number }[];
    demand_trend: { period: string; predicted_change_pct: number }[];
    confidence: number;
  };
  macro_data?: Record<string, unknown>;
}

interface MacroDataPoint {
  year: number;
  value: number;
  unit: string;
  yoy_change?: number;
}

interface MacroDataResponse {
  province: string;
  data?: Record<string, MacroDataPoint[]>;
  highlights?: string[];
}
