/**
 * Modal for creating and editing custom XBRL concept mappings.
 */

import React, { useCallback, useEffect, useState } from 'react';
import { X, Save } from 'lucide-react';
import { useMappings } from '../../hooks/useMappings';
import { FormulaEditor } from './FormulaEditor';
import { mappingsBridge } from '../../lib/mappingsBridge';
import type { AvailableXbrlConcept } from '../../types/financial';
import {
  TARGET_FIELD_DISPLAY_NAMES,
  UNIT_FAMILIES,
  createMapping,
  createFormulaMapping,
  getCustomConcept,
  getFormulaExpression,
  isConceptMapping,
  isFormulaMapping,
  type CustomXbrlConceptMapping,
  type TargetField,
  type UnitFamily,
  type FormulaValidationResult,
} from '../../types/mappings';

interface MappingEditorModalProps {
  mappingId: string | null;
  onClose: () => void;
  onSave: (mapping: CustomXbrlConceptMapping) => Promise<void>;
}

export const MappingEditorModal: React.FC<MappingEditorModalProps> = ({
  mappingId,
  onClose,
  onSave,
}) => {
  const { mappings } = useMappings();
  const isEditing = mappingId !== null;

  const [mappingType, setMappingType] = useState<'concept' | 'formula'>('concept');
  const [targetField, setTargetField] = useState<TargetField>('total_revenues');
  const [taxonomy, setTaxonomy] = useState('us-gaap');
  const [concept, setConcept] = useState('');
  const [unitFamily, setUnitFamily] = useState<UnitFamily>('currency');
  const [formula, setFormula] = useState('');
  const [formulaValidation, setFormulaValidation] = useState<FormulaValidationResult | null>(null);
  const [ticker, setTicker] = useState('');
  const [periodStart, setPeriodStart] = useState('');
  const [periodEnd, setPeriodEnd] = useState('');
  const [notes, setNotes] = useState('');
  const [enabled, setEnabled] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [isSaving, setIsSaving] = useState(false);
  const [isLoadingConcepts, setIsLoadingConcepts] = useState(false);
  const [availableConcepts, setAvailableConcepts] = useState<AvailableXbrlConcept[]>([]);

  const loadConcepts = useCallback(async (tickerValue: string) => {
    setIsLoadingConcepts(true);
    try {
      const concepts = await mappingsBridge.getTickerConcepts(tickerValue.trim());
      setAvailableConcepts(concepts);
    } catch (err) {
      console.error('Failed to load concepts:', err);
      setAvailableConcepts([]);
    } finally {
      setIsLoadingConcepts(false);
    }
  }, []);

  // Load common concepts when modal opens
  useEffect(() => {
    loadConcepts('');
  }, [loadConcepts]);

  // Reload concepts when ticker changes (debounced)
  useEffect(() => {
    const timer = setTimeout(() => {
      loadConcepts(ticker);
    }, 500);

    return () => clearTimeout(timer);
  }, [ticker, loadConcepts]);

  // Load existing mapping if editing
  useEffect(() => {
    if (mappingId) {
      const mapping = mappings.find((m) => m.id === mappingId);
      if (mapping) {
        setTargetField(mapping.targetField);
        setTicker(mapping.scope.ticker || '');
        setPeriodStart(mapping.scope.periodStart || '');
        setPeriodEnd(mapping.scope.periodEnd || '');
        setNotes(mapping.notes || '');
        setEnabled(mapping.enabled);

        if (isConceptMapping(mapping)) {
          setMappingType('concept');
          const customConcept = getCustomConcept(mapping);
          if (customConcept) {
            setTaxonomy(customConcept.taxonomy);
            setConcept(customConcept.concept);
            setUnitFamily(customConcept.unitFamily);
          }
        } else if (isFormulaMapping(mapping)) {
          setMappingType('formula');
          setFormula(getFormulaExpression(mapping) || '');
        }
      }
    } else {
      setEnabled(true);
    }
  }, [mappingId, mappings]);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setError(null);

    // Validate based on mapping type
    if (mappingType === 'concept') {
      if (!concept.trim()) {
        setError('Concept name is required');
        return;
      }

      if (!taxonomy.trim()) {
        setError('Taxonomy is required');
        return;
      }
    } else {
      if (!formula.trim()) {
        setError('Formula expression is required');
        return;
      }

      let validation = formulaValidation;
      if (!validation) {
        try {
          validation = await mappingsBridge.validateFormula(formula.trim());
          setFormulaValidation(validation);
        } catch (err) {
          setError(err instanceof Error ? err.message : 'Formula validation failed');
          return;
        }
      }

      if (!validation.isValid) {
        setError('Formula is invalid: ' + (validation.error || 'check syntax and field names'));
        return;
      }
    }

    // Validate period dates
    if (periodStart && periodEnd) {
      const startDate = new Date(periodStart);
      const endDate = new Date(periodEnd);
      if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
        setError('Invalid date format');
        return;
      }
      if (endDate < startDate) {
        setError('Period end date must be after or equal to start date');
        return;
      }
    }

    setIsSaving(true);
    try {
      const scope = {
        ticker: ticker.trim() || undefined,
        periodStart: periodStart.trim() || undefined,
        periodEnd: periodEnd.trim() || undefined,
      };

      let mapping: CustomXbrlConceptMapping;

      if (mappingType === 'concept') {
        mapping = createMapping(
          targetField,
          {
            taxonomy: taxonomy.trim(),
            concept: concept.trim(),
            unitFamily,
          },
          scope,
          notes.trim() || undefined
        );
        mapping.id = mappingId || crypto.randomUUID();
        mapping.enabled = enabled;
      } else {
        mapping = createFormulaMapping(
          targetField,
          formula.trim(),
          scope,
          notes.trim() || undefined
        );
        mapping.id = mappingId || crypto.randomUUID();
        mapping.enabled = enabled;
      }

      await onSave(mapping);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to save mapping');
    } finally {
      setIsSaving(false);
    }
  };

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
      <div className="w-full max-w-2xl max-h-[90vh] overflow-y-auto m-4 rounded-lg bg-term-surface shadow-xl">
        {/* Header */}
        <div className="sticky top-0 z-10 flex items-center justify-between border-b border-term-border bg-term-surface px-6 py-4">
          <h2 className="text-base font-mono font-semibold text-term-text">
            {isEditing ? 'Edit Custom Mapping' : 'Add Custom Mapping'}
          </h2>
          <button
            onClick={onClose}
            className="rounded border border-term-border bg-term-highlight p-2 text-term-text-muted transition-colors hover:border-term-border-focus hover:text-term-text"
            aria-label="Close modal"
          >
            <X className="h-4 w-4" />
          </button>
        </div>

        {/* Form */}
        <form onSubmit={handleSubmit} className="px-6 py-4 space-y-6">
          {/* Error Message */}
          {error && (
            <div className="rounded-lg border border-[var(--term-status-error-border)] bg-[var(--term-status-error)] px-4 py-3 text-sm font-mono text-negative">
              {error}
            </div>
          )}

          {/* Target Field */}
          <div>
            <label className="mb-2 block text-xs font-mono text-term-text-muted">
              Target Field <span className="text-negative">*</span>
            </label>
            <select
              value={targetField}
              onChange={(e) => setTargetField(e.target.value as TargetField)}
              className="w-full rounded border border-term-border bg-term-surface px-3 py-2 text-sm font-mono text-term-text outline-none transition-colors focus:border-info"
              required
            >
              {Object.entries(TARGET_FIELD_DISPLAY_NAMES).map(([value, label]) => (
                <option key={value} value={value}>
                  {label}
                </option>
              ))}
            </select>
            <p className="mt-1.5 text-xs font-mono text-term-text-muted">
              The financial field this mapping applies to
            </p>
          </div>

          {/* Mapping Type Selector */}
          <div>
            <label className="mb-2 block text-xs font-mono text-term-text-muted">
              Mapping Type <span className="text-negative">*</span>
            </label>
            <div className="flex gap-4">
              <label className="flex items-center gap-2">
                <input
                  type="radio"
                  name="mappingType"
                  checked={mappingType === 'concept'}
                  onChange={() => setMappingType('concept')}
                  className="accent-info"
                />
                <span className="text-sm text-term-text">XBRL Concept</span>
              </label>
              <label className="flex items-center gap-2">
                <input
                  type="radio"
                  name="mappingType"
                  checked={mappingType === 'formula'}
                  onChange={() => setMappingType('formula')}
                  className="accent-info"
                />
                <span className="text-sm text-term-text">Formula</span>
              </label>
            </div>
          </div>

          {/* Concept or Formula Editor */}
          {mappingType === 'concept' ? (
            <div className="rounded border border-term-border-subtle bg-term-bg p-4">
              <h3 className="mb-3 text-xs font-mono font-semibold text-term-text">
                Custom XBRL Concept <span className="text-negative">*</span>
              </h3>

              <div className="grid gap-4 sm:grid-cols-2">
                {/* Taxonomy */}
                <div>
                  <label className="mb-2 block text-xs font-mono text-term-text-muted">
                    Taxonomy <span className="text-negative">*</span>
                  </label>
                  <input
                    type="text"
                    value={taxonomy}
                    onChange={(e) => setTaxonomy(e.target.value)}
                    placeholder="e.g., us-gaap, ifrs-full, xyz-custom"
                    className="w-full rounded border border-term-border bg-term-surface px-3 py-2 text-sm font-mono text-term-text outline-none transition-colors focus:border-info"
                    required={mappingType === 'concept'}
                  />
                  <p className="mt-1.5 text-xs font-mono text-term-text-muted">XBRL taxonomy namespace</p>
                </div>

                {/* Concept Name */}
                <div>
                  <label className="mb-2 block text-xs font-mono text-term-text-muted">
                    Concept Name <span className="text-negative">*</span>
                  </label>
                  <input
                    type="text"
                    value={concept}
                    onChange={(e) => setConcept(e.target.value)}
                    placeholder="e.g., AlternativeRevenue"
                    className="w-full rounded border border-term-border bg-term-surface px-3 py-2 text-sm font-mono text-term-text outline-none transition-colors focus:border-info"
                    required={mappingType === 'concept'}
                  />
                  <p className="mt-1.5 text-xs font-mono text-term-text-muted">XBRL concept name</p>
                </div>
              </div>

              {/* Unit Family */}
              <div className="mt-4">
                <label className="mb-2 block text-xs font-mono text-term-text-muted">
                  Unit Family <span className="text-negative">*</span>
                </label>
                <select
                  value={unitFamily}
                  onChange={(e) => setUnitFamily(e.target.value as UnitFamily)}
                  className="w-full rounded border border-term-border bg-term-surface px-3 py-2 text-sm font-mono text-term-text outline-none transition-colors focus:border-info"
                  required={mappingType === 'concept'}
                >
                  {UNIT_FAMILIES.map((family) => (
                    <option key={family} value={family}>
                      {family.replace('_', ' ').toUpperCase()}
                    </option>
                  ))}
                </select>
                <p className="mt-1.5 text-xs font-mono text-term-text-muted">Unit type for this concept</p>
              </div>
            </div>
          ) : (
            <div className="rounded border border-term-border-subtle bg-term-bg p-4">
              <h3 className="mb-3 text-xs font-mono font-semibold text-term-text">
                Formula Expression <span className="text-negative">*</span>
              </h3>

              {/* Show available concepts count */}
              {isLoadingConcepts ? (
                <div className="mb-2 text-xs text-term-text-muted">
                  Loading XBRL concepts...
                </div>
              ) : availableConcepts.length > 0 && (
                <div className="mb-2 text-xs text-term-text-muted">
                  {ticker
                    ? `${availableConcepts.length} XBRL concepts from ${ticker} filing`
                    : `${availableConcepts.length} common XBRL concepts available for autocomplete`}
                </div>
              )}

              <FormulaEditor
                value={formula}
                onChange={setFormula}
                onValidate={setFormulaValidation}
                placeholder="e.g., ($gross_profit / $total_revenues) * 100"
                availableConcepts={availableConcepts}
              />
              <p className="mt-2 text-xs font-mono text-term-text-muted">
                Use <code>$field_name</code> to reference fields (type <code>$</code> for autocomplete). Type <code>#</code> for XBRL concepts. Formulas are evaluated when XBRL data is loaded.
              </p>
            </div>
          )}

          {/* Scope */}
          <div className="rounded border border-term-border-subtle bg-term-bg p-4">
            <h3 className="mb-3 text-xs font-mono font-semibold text-term-text">Scope (Optional)</h3>

            {/* Ticker */}
            <div className="mb-4">
              <label className="mb-2 block text-xs font-mono text-term-text-muted">Ticker Symbol</label>
              <input
                type="text"
                value={ticker}
                onChange={(e) => setTicker(e.target.value.toUpperCase())}
                placeholder="e.g., AAPL"
                className="w-full rounded border border-term-border bg-term-surface px-3 py-2 text-sm font-mono text-term-text outline-none transition-colors focus:border-info"
              />
              <p className="mt-1.5 text-xs font-mono text-term-text-muted">
                Leave empty for a global mapping (applies to all tickers)
              </p>
            </div>

            {/* Period */}
            <div className="grid gap-4 sm:grid-cols-2">
              <div>
                <label className="mb-2 block text-xs font-mono text-term-text-muted">Period Start</label>
                <input
                  type="date"
                  value={periodStart}
                  onChange={(e) => setPeriodStart(e.target.value)}
                  className="w-full rounded border border-term-border bg-term-surface px-3 py-2 text-sm font-mono text-term-text outline-none transition-colors focus:border-info"
                />
              </div>
              <div>
                <label className="mb-2 block text-xs font-mono text-term-text-muted">Period End</label>
                <input
                  type="date"
                  value={periodEnd}
                  onChange={(e) => setPeriodEnd(e.target.value)}
                  className="w-full rounded border border-term-border bg-term-surface px-3 py-2 text-sm font-mono text-term-text outline-none transition-colors focus:border-info"
                />
              </div>
            </div>
            <p className="mt-1.5 text-xs font-mono text-term-text-muted">
              Date range for when this mapping applies (optional)
            </p>
          </div>

          {/* Notes */}
          <div>
            <label className="mb-2 block text-xs font-mono text-term-text-muted">Notes (Optional)</label>
            <textarea
              value={notes}
              onChange={(e) => setNotes(e.target.value)}
              placeholder="e.g., Changed reporting structure in 2023"
              rows={2}
              className="w-full rounded border border-term-border bg-term-surface px-3 py-2 text-sm font-mono text-term-text outline-none transition-colors focus:border-info resize-none"
            />
            <p className="mt-1.5 text-xs font-mono text-term-text-muted">Document why this mapping is needed</p>
          </div>

          {/* Actions */}
          <div className="flex justify-end gap-3 border-t border-term-border pt-4">
            <button
              type="button"
              onClick={onClose}
              className="rounded border border-term-border bg-term-highlight px-4 py-2 text-xs font-mono text-term-text-muted transition-colors hover:border-term-border-focus hover:text-term-text"
              disabled={isSaving}
            >
              Cancel
            </button>
            <button
              type="submit"
              disabled={isSaving}
              className="inline-flex items-center gap-2 rounded border border-info bg-[var(--term-status-info)] px-4 py-2 text-xs font-mono text-info transition-colors hover:brightness-110 disabled:cursor-not-allowed disabled:opacity-50"
            >
              {isSaving ? (
                <>
                  <Save className="h-3.5 w-3.5 animate-spin" />
                  Saving...
                </>
              ) : (
                <>
                  <Save className="h-3.5 w-3.5" />
                  {isEditing ? 'Save Changes' : 'Add Mapping'}
                </>
              )}
            </button>
          </div>
        </form>
      </div>
    </div>
  );
};
