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

const DEFAULT_COLLECTION = 'industrial_parks';

const INDUSTRIAL_PROPERTY_TYPES = [
  'industrial_land',
  'ready_built_factory',
  'ready_built_warehouse',
  'logistics_center',
  'office_in_park',
  'data_center',
] as const;

const PARK_STATUSES = ['planning', 'under_construction', 'operational', 'full'] as const;

const REGIONS = ['north', 'central', 'south'] as const;

const SearchIndustrialParksSchema = {
  query: z.string().describe('Natural language search query (e.g. "KCN Bình Dương còn đất trống")'),
  province: z.string().optional().describe('Filter by province (e.g. "Bình Dương", "Đồng Nai")'),
  region: z.enum(REGIONS).optional().describe('Filter by region'),
  status: z.enum(PARK_STATUSES).optional().describe('Filter by park status'),
  minAreaHa: z.number().optional().describe('Minimum remaining leasable area in hectares'),
  maxRentUsdM2: z.number().optional().describe('Maximum land rent in USD/m²/year'),
  targetIndustry: z.string().optional().describe('Target industry (e.g. "electronics", "logistics", "food processing")'),
  hasReadyBuilt: z.boolean().optional().describe('Filter parks with ready-built factory/warehouse'),
  latitude: z.number().optional().describe('Center latitude for geo search'),
  longitude: z.number().optional().describe('Center longitude for geo search'),
  radiusKm: z.number().optional().describe('Radius in km for geo search'),
  sortBy: z.enum(['relevance', 'rent_asc', 'rent_desc', 'occupancy_asc', 'area_desc', 'distance']).optional(),
  page: z.number().int().min(1).default(1),
  perPage: z.number().int().min(1).max(50).default(20),
};

const AnalyzeIndustrialLocationSchema = {
  parkName: z.string().optional().describe('Industrial park name to analyze'),
  latitude: z.number().describe('Latitude of the location'),
  longitude: z.number().describe('Longitude of the location'),
  targetIndustry: z.string().optional().describe('Industry type for relevance scoring'),
};

const EstimateIndustrialRentSchema = {
  province: z.string().describe('Province name'),
  propertyType: z.enum(INDUSTRIAL_PROPERTY_TYPES).describe('Type of industrial property'),
  areaM2: z.number().positive().describe('Required area in m²'),
  leaseDurationYears: z.number().int().min(1).max(70).default(10).describe('Lease duration in years'),
  parkName: z.string().optional().describe('Specific industrial park name for precise estimate'),
  requiresCrane: z.boolean().optional().describe('Requires overhead crane'),
  requiredPowerKva: z.number().optional().describe('Required power capacity in KVA'),
  requiresWastewater: z.boolean().optional().describe('Requires wastewater treatment'),
};

export function createIndustrialParksServer(deps: IndustrialParksDeps): McpServer {
  const collectionName = deps.collectionName ?? DEFAULT_COLLECTION;
  const client = deps.typesenseClient;
  const baseUrl = deps.aiServiceBaseUrl.replace(/\/$/, '');

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

  server.tool(
    'search_industrial_parks',
    'Search Vietnamese industrial parks and zones with filters for province, area, rent, and target industry.',
    SearchIndustrialParksSchema,
    async (params: z.infer<z.ZodObject<typeof SearchIndustrialParksSchema>>) => {
      const filters: string[] = [];

      if (params.province) filters.push(`province:=${params.province}`);
      if (params.region) filters.push(`region:=${params.region}`);
      if (params.status) filters.push(`status:=${params.status}`);
      if (params.minAreaHa != null) filters.push(`remainingAreaHa:>=${params.minAreaHa}`);
      if (params.maxRentUsdM2 != null) filters.push(`landRentUsdM2Year:<=${params.maxRentUsdM2}`);
      if (params.targetIndustry) filters.push(`targetIndustries:=${params.targetIndustry}`);
      if (params.hasReadyBuilt) filters.push(`hasReadyBuilt:=true`);

      let filterBy = filters.join(' && ');

      if (params.latitude != null && params.longitude != null && params.radiusKm) {
        const geoFilter = `location:(${params.latitude}, ${params.longitude}, ${params.radiusKm} km)`;
        filterBy = filterBy ? `${filterBy} && ${geoFilter}` : geoFilter;
      }

      let sortBy = 'occupancyRate:asc';
      if (params.sortBy === 'rent_asc') sortBy = 'landRentUsdM2Year:asc';
      else if (params.sortBy === 'rent_desc') sortBy = 'landRentUsdM2Year:desc';
      else if (params.sortBy === 'occupancy_asc') sortBy = 'occupancyRate:asc';
      else if (params.sortBy === 'area_desc') sortBy = 'remainingAreaHa:desc';
      else if (params.sortBy === 'distance' && params.latitude != null && params.longitude != null) {
        sortBy = `location(${params.latitude}, ${params.longitude}):asc`;
      } else if (params.sortBy === 'relevance' && params.query) {
        sortBy = '_text_match:desc,occupancyRate:asc';
      }

      const result = await client
        .collections(collectionName)
        .documents()
        .search({
          q: params.query || '*',
          query_by: 'name,nameEn,developer,operator,province,targetIndustries',
          query_by_weights: '5,4,2,2,3,3',
          filter_by: filterBy || undefined,
          sort_by: sortBy,
          page: params.page,
          per_page: params.perPage,
        });

      const hits = (result.hits ?? []).map((hit) => {
        const doc = hit.document as Record<string, unknown>;
        return {
          parkId: doc['parkId'],
          name: doc['name'],
          nameEn: doc['nameEn'] ?? null,
          developer: doc['developer'],
          province: doc['province'],
          region: doc['region'],
          status: doc['status'],
          totalAreaHa: doc['totalAreaHa'],
          remainingAreaHa: doc['remainingAreaHa'],
          occupancyRate: doc['occupancyRate'],
          landRentUsdM2Year: doc['landRentUsdM2Year'] ?? null,
          rbfRentUsdM2Month: doc['rbfRentUsdM2Month'] ?? null,
          rbwRentUsdM2Month: doc['rbwRentUsdM2Month'] ?? null,
          targetIndustries: doc['targetIndustries'] ?? [],
          tenantCount: doc['tenantCount'] ?? 0,
        };
      });

      return {
        content: [{
          type: 'text' as const,
          text: JSON.stringify({
            totalFound: result.found ?? 0,
            page: params.page,
            perPage: params.perPage,
            searchTimeMs: result.search_time_ms ?? 0,
            results: hits,
          }, null, 2),
        }],
      };
    },
  );

  server.tool(
    'analyze_industrial_location',
    'Analyze an industrial location for connectivity, infrastructure, and suitability scoring.',
    AnalyzeIndustrialLocationSchema,
    async (params: z.infer<z.ZodObject<typeof AnalyzeIndustrialLocationSchema>>) => {
      const response = await fetch(`${baseUrl}/industrial/analyze-location`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          park_name: params.parkName ?? null,
          latitude: params.latitude,
          longitude: params.longitude,
          target_industry: params.targetIndustry ?? null,
        }),
      });

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

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

      return {
        content: [{
          type: 'text' as const,
          text: JSON.stringify({
            overallScore: data.overall_score,
            connectivity: {
              nearestPort: data.connectivity?.nearest_port ?? null,
              nearestAirport: data.connectivity?.nearest_airport ?? null,
              nearestHighway: data.connectivity?.nearest_highway ?? null,
              nearestRailway: data.connectivity?.nearest_railway ?? null,
            },
            infrastructure: {
              powerAvailability: data.infrastructure?.power_availability ?? null,
              waterSupply: data.infrastructure?.water_supply ?? null,
              wastewaterTreatment: data.infrastructure?.wastewater_treatment ?? null,
              telecom: data.infrastructure?.telecom ?? null,
            },
            laborMarket: {
              workerPoolRadius30km: data.labor_market?.worker_pool_radius_30km ?? null,
              averageWageUsd: data.labor_market?.average_wage_usd ?? null,
              nearbyUniversities: data.labor_market?.nearby_universities ?? [],
            },
            incentives: data.incentives ?? [],
            risks: data.risks ?? [],
          }, null, 2),
        }],
      };
    },
  );

  server.tool(
    'estimate_industrial_rent',
    'Estimate rental costs for industrial property based on province, type, area, and requirements.',
    EstimateIndustrialRentSchema,
    async (params: z.infer<z.ZodObject<typeof EstimateIndustrialRentSchema>>) => {
      const response = await fetch(`${baseUrl}/industrial/estimate-rent`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          province: params.province,
          property_type: params.propertyType,
          area_m2: params.areaM2,
          lease_duration_years: params.leaseDurationYears,
          park_name: params.parkName ?? null,
          requires_crane: params.requiresCrane ?? false,
          required_power_kva: params.requiredPowerKva ?? null,
          requires_wastewater: params.requiresWastewater ?? false,
        }),
      });

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

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

      return {
        content: [{
          type: 'text' as const,
          text: JSON.stringify({
            estimatedRentUsdM2: data.estimated_rent_usd_m2,
            pricingUnit: data.pricing_unit,
            totalMonthlyUsd: data.total_monthly_usd,
            totalLeaseUsd: data.total_lease_usd,
            managementFeeUsdM2: data.management_fee_usd_m2 ?? null,
            depositMonths: data.deposit_months ?? null,
            marketComparison: {
              provinceLow: data.market_comparison?.province_low ?? null,
              provinceHigh: data.market_comparison?.province_high ?? null,
              provinceAvg: data.market_comparison?.province_avg ?? null,
            },
            breakdown: data.breakdown ?? [],
            input: {
              province: params.province,
              propertyType: params.propertyType,
              areaM2: params.areaM2,
              leaseDurationYears: params.leaseDurationYears,
            },
          }, null, 2),
        }],
      };
    },
  );

  return server;
}

// Response types from the AI service
interface IndustrialLocationAnalysis {
  overall_score: number;
  connectivity?: {
    nearest_port?: { name: string; distanceKm: number };
    nearest_airport?: { name: string; distanceKm: number };
    nearest_highway?: { name: string; distanceKm: number };
    nearest_railway?: { name: string; distanceKm: number };
  };
  infrastructure?: {
    power_availability?: string;
    water_supply?: string;
    wastewater_treatment?: string;
    telecom?: string;
  };
  labor_market?: {
    worker_pool_radius_30km?: number;
    average_wage_usd?: number;
    nearby_universities?: string[];
  };
  incentives?: string[];
  risks?: string[];
}

interface IndustrialRentEstimate {
  estimated_rent_usd_m2: number;
  pricing_unit: string;
  total_monthly_usd: number;
  total_lease_usd: number;
  management_fee_usd_m2?: number;
  deposit_months?: number;
  market_comparison?: {
    province_low?: number;
    province_high?: number;
    province_avg?: number;
  };
  breakdown?: { item: string; amount: number }[];
}
