import { IconLayer, TextLayer } from '@deck.gl/layers';
import type { PickingInfo, Layer } from '@deck.gl/core';
import { svgToDataUri } from '../../utils/svgToDataUri';
import { FONT_MONO } from '../../styles/fonts';
import { iranOilFacilities } from '../../data/oilFacilities';
import type { OilFacility, OilFacilityType } from '../../types';

export const IRAN_OIL_COUNT = iranOilFacilities.length;

// ─── Type colors ──────────────────────────────────────────────────────────────

const TYPE_COLORS: Record<OilFacilityType, string> = {
  refinery: '#fb7185',
  oilfield: '#34d399',
  gasfield: '#818cf8',
  terminal: '#c084fc',
  petrochemical: '#f472b6',
  desalination: '#22d3ee',
};

// ─── SVG generators ──────────────────────────────────────────────────────────

function damageOverlaySvg(): string {
  return `<line x1="4" y1="4" x2="32" y2="32" stroke="#ff0000" stroke-width="2.5" opacity="0.8"/>
    <line x1="32" y1="4" x2="4" y2="32" stroke="#ff0000" stroke-width="2.5" opacity="0.8"/>
    <circle cx="18" cy="18" r="15" fill="none" stroke="#ff0000" stroke-width="1.5" opacity="0.4"/>`;
}

function plannedOverlaySvg(): string {
  return `<circle cx="18" cy="18" r="15" fill="none" stroke="#ff6600" stroke-width="2" stroke-dasharray="4 3" opacity="0.9"/>
    <line x1="18" y1="0" x2="18" y2="4" stroke="#ff6600" stroke-width="1.5" opacity="0.7"/>
    <line x1="18" y1="32" x2="18" y2="36" stroke="#ff6600" stroke-width="1.5" opacity="0.7"/>
    <line x1="0" y1="18" x2="4" y2="18" stroke="#ff6600" stroke-width="1.5" opacity="0.7"/>
    <line x1="32" y1="18" x2="36" y2="18" stroke="#ff6600" stroke-width="1.5" opacity="0.7"/>`;
}

function refinerySvg(color: string, damaged: boolean, planned: boolean): string {
  const sc = damaged ? '#ff0000' : color;
  return `<svg width="36" height="36" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg">
    <defs>
      <linearGradient id="refGrad" x1="0" y1="0" x2="1" y2="1">
        <stop offset="0%" stop-color="${color}" stop-opacity="0.5"/>
        <stop offset="100%" stop-color="${color}" stop-opacity="0.2"/>
      </linearGradient>
    </defs>
    <circle cx="18" cy="18" r="17" fill="url(#refGrad)" stroke="${sc}" stroke-width="${damaged ? 2 : 1}" opacity="0.9"/>
    <rect x="6" y="19" width="24" height="11" rx="1" fill="${color}" opacity="0.6"/>
    <rect x="16" y="7" width="4" height="13" fill="${color}" opacity="0.7"/>
    <rect x="9" y="12" width="4" height="8" fill="${color}" opacity="0.65"/>
    <rect x="23" y="10" width="4" height="10" fill="${color}" opacity="0.65"/>
    <circle cx="11" cy="10" r="1.5" fill="${color}" opacity="0.3"/>
    <circle cx="18" cy="5" r="2" fill="${color}" opacity="0.3"/>
    <circle cx="25" cy="8" r="1.5" fill="${color}" opacity="0.3"/>
    <rect x="10" y="22" width="3" height="3" rx="0.5" fill="rgba(0,0,0,0.4)"/>
    <rect x="16" y="22" width="3" height="3" rx="0.5" fill="rgba(0,0,0,0.4)"/>
    <rect x="23" y="22" width="3" height="3" rx="0.5" fill="rgba(0,0,0,0.4)"/>
    <line x1="13" y1="15" x2="16" y2="15" stroke="${color}" stroke-width="0.8" opacity="0.5"/>
    <line x1="20" y1="13" x2="23" y2="13" stroke="${color}" stroke-width="0.8" opacity="0.5"/>
    ${damaged ? damageOverlaySvg() : ''}
    ${planned ? plannedOverlaySvg() : ''}
  </svg>`;
}

function oilfieldSvg(color: string, damaged: boolean, planned: boolean): string {
  const sc = damaged ? '#ff0000' : color;
  return `<svg width="36" height="36" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg">
    <rect x="4" y="31" width="28" height="2.5" rx="1" fill="${color}" opacity="0.7"/>
    <line x1="18" y1="14" x2="12" y2="31" stroke="${sc}" stroke-width="1.5" opacity="0.85"/>
    <line x1="18" y1="14" x2="24" y2="31" stroke="${sc}" stroke-width="1.5" opacity="0.85"/>
    <line x1="14" y1="25" x2="22" y2="25" stroke="${color}" stroke-width="1" opacity="0.7"/>
    <line x1="4" y1="12" x2="28" y2="10" stroke="${sc}" stroke-width="2" opacity="0.9"/>
    <circle cx="18" cy="13" r="2" fill="${color}" opacity="0.8" stroke="${sc}" stroke-width="1"/>
    <path d="M4 12 L4 17 L7 17 L7 12" fill="none" stroke="${sc}" stroke-width="1.5" opacity="0.85"/>
    <line x1="5.5" y1="17" x2="5.5" y2="31" stroke="${color}" stroke-width="1.2" opacity="0.75"/>
    <rect x="25" y="10" width="5" height="6" rx="1" fill="${color}" opacity="0.6" stroke="${sc}" stroke-width="1"/>
    <line x1="27.5" y1="16" x2="27.5" y2="24" stroke="${color}" stroke-width="1.2" opacity="0.75"/>
    <rect x="24" y="24" width="7" height="5" rx="1" fill="${color}" opacity="0.55" stroke="${sc}" stroke-width="1"/>
    <rect x="3" y="28" width="5" height="3" rx="0.5" fill="${color}" opacity="0.65" stroke="${sc}" stroke-width="0.8"/>
    <path d="M5.5 29 C5.5 29 4.5 30 4.5 30.5 C4.5 31 5 31.2 5.5 31.2 C6 31.2 6.5 31 6.5 30.5 C6.5 30 5.5 29 5.5 29Z" fill="${color}" opacity="0.85"/>
    ${damaged ? damageOverlaySvg() : ''}
    ${planned ? plannedOverlaySvg() : ''}
  </svg>`;
}

function gasfieldSvg(color: string, damaged: boolean, planned: boolean): string {
  return `<svg width="36" height="36" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg">
    <line x1="10" y1="24" x2="8" y2="33" stroke="${color}" stroke-width="1.5" opacity="0.7"/>
    <line x1="14" y1="25" x2="13" y2="33" stroke="${color}" stroke-width="1.5" opacity="0.7"/>
    <line x1="22" y1="25" x2="23" y2="33" stroke="${color}" stroke-width="1.5" opacity="0.7"/>
    <line x1="26" y1="24" x2="28" y2="33" stroke="${color}" stroke-width="1.5" opacity="0.7"/>
    <line x1="9" y1="29" x2="14" y2="27" stroke="${color}" stroke-width="0.8" opacity="0.55"/>
    <line x1="22" y1="27" x2="27" y2="29" stroke="${color}" stroke-width="0.8" opacity="0.55"/>
    <line x1="7" y1="33" x2="29" y2="33" stroke="${color}" stroke-width="1.2" opacity="0.6"/>
    <ellipse cx="18" cy="16" rx="12" ry="10" fill="${color}" opacity="0.45" stroke="${damaged ? '#ff0000' : color}" stroke-width="1.5"/>
    <ellipse cx="16" cy="12" rx="7" ry="5" fill="${color}" opacity="0.3"/>
    <ellipse cx="18" cy="16" rx="12" ry="2.5" fill="none" stroke="${color}" stroke-width="0.8" opacity="0.55"/>
    <rect x="16.5" y="4" width="3" height="3" rx="0.5" fill="${color}" opacity="0.7"/>
    <line x1="18" y1="4" x2="18" y2="6" stroke="${color}" stroke-width="1.5" opacity="0.7"/>
    ${damaged ? damageOverlaySvg() : ''}
    ${planned ? plannedOverlaySvg() : ''}
  </svg>`;
}

function terminalSvg(color: string, damaged: boolean, planned: boolean): string {
  const sc = damaged ? '#ff0000' : color;
  return `<svg width="36" height="36" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg">
    <circle cx="18" cy="10" r="4" fill="none" stroke="${sc}" stroke-width="2"/>
    <line x1="18" y1="14" x2="18" y2="28" stroke="${color}" stroke-width="2"/>
    <path d="M10 24 C10 28 14 32 18 32 C22 32 26 28 26 24" fill="none" stroke="${color}" stroke-width="2"/>
    <line x1="18" y1="8" x2="18" y2="6" stroke="${color}" stroke-width="2"/>
    <line x1="16" y1="6" x2="20" y2="6" stroke="${color}" stroke-width="2.5"/>
    <path d="M6 24 L10 24" stroke="${color}" stroke-width="1.5"/>
    <path d="M26 24 L30 24" stroke="${color}" stroke-width="1.5"/>
    <polygon points="5,24 8,22 8,26" fill="${color}" opacity="0.7"/>
    <polygon points="31,24 28,22 28,26" fill="${color}" opacity="0.7"/>
    ${damaged ? damageOverlaySvg() : ''}
    ${planned ? plannedOverlaySvg() : ''}
  </svg>`;
}

function petrochemSvg(color: string, damaged: boolean, planned: boolean): string {
  const sc = damaged ? '#ff0000' : '#fff';
  return `<svg width="36" height="36" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg">
    <path d="M14 6 L14 16 L8 30 L28 30 L22 16 L22 6Z" fill="${color}" opacity="0.7" stroke="${sc}" stroke-width="1"/>
    <rect x="13" y="4" width="10" height="4" rx="1" fill="${color}" opacity="0.9" stroke="${sc}" stroke-width="0.8"/>
    <path d="M11 22 L25 22 L28 30 L8 30Z" fill="${color}" opacity="0.5"/>
    <circle cx="16" cy="25" r="1.5" fill="#c4b5fd" opacity="0.7"/>
    <circle cx="20" cy="23" r="1" fill="#c4b5fd" opacity="0.6"/>
    <circle cx="18" cy="27" r="1.2" fill="#c4b5fd" opacity="0.5"/>
    ${damaged ? damageOverlaySvg() : ''}
    ${planned ? plannedOverlaySvg() : ''}
  </svg>`;
}

function desalSvg(color: string, damaged: boolean, planned: boolean): string {
  const sc = damaged ? '#ff0000' : color;
  return `<svg width="36" height="36" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg">
    <path d="M14 3 C14 3 6 14 6 19 C6 23.5 9.5 27 14 27 C18.5 27 22 23.5 22 19 C22 14 14 3 14 3Z" fill="${color}" opacity="0.4" stroke="${sc}" stroke-width="1.2"/>
    <path d="M14 10 C14 10 10 16 10 19 C10 21.5 11.8 23.5 14 23.5 C16.2 23.5 18 21.5 18 19 C18 16 14 10 14 10Z" fill="${color}" opacity="0.3"/>
    <rect x="24" y="5" width="6" height="3" rx="1" fill="${color}" opacity="0.5" stroke="${sc}" stroke-width="0.8"/>
    <line x1="27" y1="8" x2="27" y2="12" stroke="${sc}" stroke-width="1.5" opacity="0.7"/>
    <path d="M24 8 L24 10 Q24 12 26 12 L28 12 Q30 12 30 10 L30 8" fill="none" stroke="${sc}" stroke-width="0.8" opacity="0.6"/>
    <circle cx="27" cy="14.5" r="1" fill="${color}" opacity="0.55"/>
    <circle cx="27" cy="17" r="0.7" fill="${color}" opacity="0.45"/>
    <rect x="23" y="20" width="9" height="12" rx="1.5" fill="${color}" opacity="0.4" stroke="${sc}" stroke-width="1"/>
    <line x1="24" y1="24" x2="31" y2="24" stroke="${color}" stroke-width="0.6" opacity="0.5"/>
    <line x1="24" y1="27" x2="31" y2="27" stroke="${color}" stroke-width="0.6" opacity="0.5"/>
    <path d="M18 22 L23 22" stroke="${sc}" stroke-width="1" opacity="0.6"/>
    <line x1="27.5" y1="32" x2="27.5" y2="34" stroke="${color}" stroke-width="1" opacity="0.55"/>
    <line x1="4" y1="34" x2="33" y2="34" stroke="${color}" stroke-width="1" opacity="0.25"/>
    ${damaged ? damageOverlaySvg() : ''}
    ${planned ? plannedOverlaySvg() : ''}
  </svg>`;
}

function buildSvg(type: OilFacilityType, color: string, damaged: boolean, planned: boolean): string {
  switch (type) {
    case 'refinery': return refinerySvg(color, damaged, planned);
    case 'oilfield': return oilfieldSvg(color, damaged, planned);
    case 'gasfield': return gasfieldSvg(color, damaged, planned);
    case 'terminal': return terminalSvg(color, damaged, planned);
    case 'petrochemical': return petrochemSvg(color, damaged, planned);
    case 'desalination': return desalSvg(color, damaged, planned);
  }
}

// ─── Module-level icon cache ─────────────────────────────────────────────────

const oilIconCache = new Map<string, string>();

function getOilIconUrl(type: OilFacilityType, damaged: boolean, planned: boolean): string {
  const key = `${type}-${damaged ? 'd' : 'n'}-${planned ? 'p' : 'n'}`;
  if (!oilIconCache.has(key)) {
    const color = TYPE_COLORS[type];
    oilIconCache.set(key, svgToDataUri(buildSvg(type, color, damaged, planned)));
  }
  return oilIconCache.get(key)!;
}

// ─── Label color ─────────────────────────────────────────────────────────────

function getLabelColor(type: OilFacilityType, damaged: boolean, planned: boolean): [number, number, number, number] {
  if (damaged) return [255, 0, 0, 255];
  if (planned) return [255, 102, 0, 255];
  const hex = TYPE_COLORS[type];
  const r = parseInt(hex.slice(1, 3), 16);
  const g = parseInt(hex.slice(3, 5), 16);
  const b = parseInt(hex.slice(5, 7), 16);
  return [r, g, b, 255];
}

// ─── Public interface ────────────────────────────────────────────────────────

export interface OilLayerConfig {
  visible: boolean;
  sc: number;
  currentTime: number;
  onPick: (f: OilFacility) => void;
}

export function createIranOilLayers(config: OilLayerConfig): Layer[] {
  if (!config.visible) return [];

  const { sc, currentTime, onPick } = config;

  return [
    new IconLayer<OilFacility>({
      id: 'iran-oil-icon',
      data: iranOilFacilities,
      getPosition: (d) => [d.lng, d.lat],
      getIcon: (d) => {
        const isDamaged = !!(d.damaged && d.damagedAt && currentTime >= d.damagedAt);
        const isPlanned = !!d.planned && !isDamaged;
        return {
          url: getOilIconUrl(d.type, isDamaged, isPlanned),
          width: 36,
          height: 36,
          anchorX: 18,
          anchorY: 18,
        };
      },
      getSize: 18 * sc,
      updateTriggers: { getSize: [sc], getIcon: [currentTime] },
      pickable: true,
      onClick: (info: PickingInfo<OilFacility>) => {
        if (info.object) onPick(info.object);
        return true;
      },
    }),
    new TextLayer<OilFacility>({
      id: 'iran-oil-label',
      data: iranOilFacilities,
      getPosition: (d) => [d.lng, d.lat],
      getText: (d) => d.nameKo,
      getSize: 9 * sc,
      updateTriggers: { getSize: [sc], getColor: [currentTime] },
      getColor: (d) => {
        const isDamaged = !!(d.damaged && d.damagedAt && currentTime >= d.damagedAt);
        const isPlanned = !!d.planned && !isDamaged;
        return getLabelColor(d.type, isDamaged, isPlanned);
      },
      getTextAnchor: 'middle',
      getAlignmentBaseline: 'top',
      getPixelOffset: [0, 10],
      fontFamily: FONT_MONO,
      fontWeight: 700,
      outlineWidth: 2,
      outlineColor: [0, 0, 0, 200],
      billboard: false,
      characterSet: 'auto',
    }),
  ];
}
