/**
 * Inline mapping editor for creating custom XBRL concept mappings from statement table cells.
 */

import React, { useCallback, useEffect, useState } from 'react';
import { X, Loader2 } from 'lucide-react';
import { useEarningsMappings } from '../../hooks/useEarningsMappings';
import {
  TARGET_FIELD_DISPLAY_NAMES,
  TARGET_FIELD_DISPLAY_NAMES as TARGET_FIELD_LABELS,
  createFormulaMapping,
  type TargetField,
  type CustomConcept,
  type UnitFamily,
  type FormulaValidationResult,
} from '../../types/mappings';
import type { EarningsMappingContext, MappingCellInfo } from '../../hooks/useEarningsMappings';
import { ConceptSelector } from './ConceptSelector';
import { FormulaEditor } from '../Settings/FormulaEditor';
import type { AvailableXbrlConcept } from '../../types/financial';
import { resolveStatementMetricTargetField } from '../../lib/statementMetricTargetFields';

interface InlineMappingEditorProps {
  /** Information about the cell being mapped */
  cellInfo: MappingCellInfo;
  /** Statement context (ticker, frequency, periods) */
  context: EarningsMappingContext;
  /** Available XBRL concepts from the filing */
  availableConcepts: AvailableXbrlConcept[];
  /** Optional pre-selected target field */
  targetField?: TargetField;
  /** Callback when mapping is created successfully */
  onSuccess?: () => void;
  /** Callback when editor is closed */
  onClose: () => void;
  /** Positioning for the popover */
  position?: { top: number; left: number };
}

interface FormState {
  mappingType: 'concept' | 'formula';
  selectedConcept: AvailableXbrlConcept | null;
  formula: string;
  formulaValidation: FormulaValidationResult | null;
  isGlobal: boolean;
  notes: string;
}

const DEFAULT_FORM_STATE: FormState = {
  mappingType: 'concept',
  selectedConcept: null,
  formula: '',
  formulaValidation: null,
  isGlobal: false,
  notes: '',
};

export function InlineMappingEditor({
  cellInfo,
  context,
  availableConcepts,
  targetField: initialTargetField,
  onSuccess,
  onClose,
  position,
}: InlineMappingEditorProps) {
  const { createMappingFromEarnings, addMapping, isLoading } = useEarningsMappings();
  const resolvedTargetField = resolveStatementMetricTargetField(cellInfo.metricKey);
  const [targetField, setTargetField] = useState<TargetField>(
    initialTargetField ?? resolvedTargetField ?? 'total_revenues'
  );
  const [form, setForm] = useState<FormState>(DEFAULT_FORM_STATE);
  const [error, setError] = useState<string | null>(null);
  const [isSubmitting, setIsSubmitting] = useState(false);

  const updateForm = useCallback((patch: Partial<FormState>) => {
    setForm((prev) => ({ ...prev, ...patch }));
  }, []);

  const resetForm = useCallback(() => {
    setForm(DEFAULT_FORM_STATE);
  }, []);

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

    if (form.mappingType === 'concept') {
      // Validation for concept mapping
      if (!form.selectedConcept) {
        setError('Please select a concept from the available options');
        return;
      }

      setIsSubmitting(true);
      try {
        const customConcept: CustomConcept = {
          taxonomy: form.selectedConcept.taxonomy,
          concept: form.selectedConcept.concept,
          unitFamily: form.selectedConcept.unitFamily as UnitFamily,
        };

        await createMappingFromEarnings(
          targetField,
          customConcept,
          context,
          {
            global: form.isGlobal,
            notes: form.notes.trim() || undefined,
          }
        );

        resetForm();
        onSuccess?.();
        onClose();
      } catch (err) {
        setError(err instanceof Error ? err.message : 'Failed to create mapping');
      } finally {
        setIsSubmitting(false);
      }
    } else {
      // Validation for formula mapping
      if (!form.formula.trim()) {
        setError('Please enter a formula expression');
        return;
      }

      if (form.formulaValidation && !form.formulaValidation.isValid) {
        setError('Formula is invalid: ' + (form.formulaValidation.error || 'Unknown error'));
        return;
      }

      setIsSubmitting(true);
      try {
        const hasIsoPeriodBounds =
          isIsoDate(context.earliestPeriod) && isIsoDate(context.latestPeriod);
        const scope = form.isGlobal
          ? {}
          : {
              ticker: context.symbol,
              periodStart: hasIsoPeriodBounds ? context.earliestPeriod : undefined,
              periodEnd: hasIsoPeriodBounds ? context.latestPeriod : undefined,
            };

        const mapping = createFormulaMapping(
          targetField,
          form.formula.trim(),
          scope,
          form.notes.trim() || undefined
        );

        // Use addMapping directly for formula mappings
        await addMapping(mapping);

        resetForm();
        onSuccess?.();
        onClose();
      } catch (err) {
        setError(err instanceof Error ? err.message : 'Failed to create formula mapping');
      } finally {
        setIsSubmitting(false);
      }
    }
  };

  useEffect(() => {
    if (initialTargetField) {
      setTargetField(initialTargetField);
      return;
    }

    setTargetField(resolvedTargetField ?? 'total_revenues');
  }, [initialTargetField, resolvedTargetField]);

  return (
    <div
      className="fixed z-50 flex w-96 flex-col overflow-visible rounded-lg border border-term-border bg-term-bg shadow-lg"
      style={{
        ...position,
        pointerEvents: 'auto',
        maxHeight: position?.top != null
          ? `calc(100vh - ${position.top}px - 12px)`
          : 'calc(100vh - 20px)',
        minHeight: '300px',
      }}
    >
      {/* Header - Fixed */}
      <div className="flex items-center justify-between border-b border-term-border-subtle px-4 py-3 flex-shrink-0">
        <div>
          <h3 className="text-sm font-semibold text-term-text">
            Map Custom XBRL Concept
          </h3>
          <p className="mt-1 text-xs text-term-text-muted">
            Create a mapping for <span className="font-medium text-term-text">{cellInfo.metricLabel}</span>
          </p>
        </div>
        <button
          onClick={onClose}
          className="rounded p-1 text-term-text-muted hover:bg-term-bg-secondary hover:text-term-text"
          aria-label="Close"
        >
          <X className="h-4 w-4" />
        </button>
      </div>

      <form onSubmit={handleSubmit} className="relative flex min-h-0 flex-1 flex-col overflow-visible">
        <div
          className="min-h-0 flex-1 p-4 pb-24"
          style={{ overflowY: 'auto', overflowX: 'visible' }}
        >
        {error && (
          <div className="mb-4 rounded-md bg-danger-bg/10 border border-danger-border/20 px-3 py-2 text-xs text-danger-text">
            {error}
          </div>
        )}

        {/* Target Field */}
        <div className="mb-4">
          <label className="mb-1.5 block text-xs font-medium text-term-text-muted">
            Target Field
          </label>
          <select
            value={targetField}
            onChange={(e) => setTargetField(e.target.value as TargetField)}
            className="w-full rounded-md border border-term-border-subtle bg-term-bg px-3 py-2 text-sm text-term-text"
          >
            {Object.entries(TARGET_FIELD_LABELS).map(([key, label]) => (
              <option key={key} value={key}>
                {label}
              </option>
            ))}
          </select>
        </div>

        {/* Mapping Type Selector */}
        <div className="mb-4">
          <label className="mb-1.5 block text-xs font-medium text-term-text-muted">
            Mapping Type
          </label>
          <div className="flex gap-4">
            <label className="flex items-center gap-2">
              <input
                type="radio"
                name="mappingType"
                checked={form.mappingType === 'concept'}
                onChange={() => updateForm({ mappingType: 'concept' })}
                className="h-4 w-4 border-term-border-subtle text-term-text focus:ring-term-border-subtle"
              />
              <span className="text-sm text-term-text">XBRL Concept</span>
            </label>
            <label className="flex items-center gap-2">
              <input
                type="radio"
                name="mappingType"
                checked={form.mappingType === 'formula'}
                onChange={() => updateForm({ mappingType: 'formula' })}
                className="h-4 w-4 border-term-border-subtle text-term-text focus:ring-term-border-subtle"
              />
              <span className="text-sm text-term-text">Formula</span>
            </label>
          </div>
        </div>

        {/* XBRL Concept Details */}
        <div className="mb-4 space-y-3" style={{ display: form.mappingType === 'concept' ? 'block' : 'none' }}>
          <div>
            <label className="mb-1.5 block text-xs font-medium text-term-text-muted">
              Select XBRL Concept
            </label>
            <ConceptSelector
              concepts={availableConcepts}
              selectedConcept={form.selectedConcept}
              onSelect={(concept) => updateForm({ selectedConcept: concept || null })}
              placeholder="Search for an XBRL concept..."
              periodId={context.latestPeriod}
            />
            <p className="mt-1 text-[10px] text-term-text-tertiary">
              Search and select from available concepts in this filing
            </p>
          </div>
        </div>

        {/* Formula Expression */}
        <div className="mb-4 space-y-3" style={{ display: form.mappingType === 'formula' ? 'block' : 'none' }}>
          <div>
            <label className="mb-1.5 block text-xs font-medium text-term-text-muted">
              Formula Expression
            </label>
            <FormulaEditor
              value={form.formula}
              onChange={(value) => {
                updateForm({ formula: value });
              }}
              onValidate={(result) => {
                updateForm({ formulaValidation: result });
              }}
              placeholder="e.g., ($gross_profit / $total_revenues) * 100"
              availableConcepts={availableConcepts}
            />
            <p className="mt-1 text-[10px] text-term-text-tertiary">
              Use $FieldName to reference other fields. Type # for XBRL concepts.
            </p>
          </div>
        </div>

        {/* Scope */}
        <div className="mb-4">
          <label className="mb-2 block text-xs font-medium text-term-text-muted">
            Mapping Scope
          </label>
          <div className="space-y-2">
            <label className="flex items-center gap-2">
              <input
                type="radio"
                name="scope"
                checked={!form.isGlobal}
                onChange={() => updateForm({ isGlobal: false })}
                className="h-4 w-4 border-term-border-subtle text-term-text focus:ring-term-border-subtle"
              />
              <span className="text-sm text-term-text">
                Ticker-specific (<span className="font-mono text-term-text-muted">{context.symbol}</span>)
              </span>
            </label>
            <label className="flex items-center gap-2">
              <input
                type="radio"
                name="scope"
                checked={form.isGlobal}
                onChange={() => updateForm({ isGlobal: true })}
                className="h-4 w-4 border-term-border-subtle text-term-text focus:ring-term-border-subtle"
              />
              <span className="text-sm text-term-text">Global (all tickers)</span>
            </label>
          </div>
        </div>

        {/* Notes */}
        <div className="mb-4">
          <label className="mb-1.5 block text-xs font-medium text-term-text-muted">
            Notes (optional)
          </label>
          <textarea
            value={form.notes}
            onChange={(e) => updateForm({ notes: e.target.value })}
            placeholder="Why this mapping is needed..."
            rows={2}
            className="w-full rounded-md border border-term-border-subtle bg-term-bg px-3 py-2 text-sm text-term-text placeholder:text-term-text-tertiary"
          />
        </div>

        {/* Preview */}
        <div className="mb-4 rounded-md bg-term-bg-secondary border border-term-border-subtle px-3 py-2">
          <div className="text-[10px] font-mono text-term-text-muted">
            <div>Target: <span className="text-term-text">{TARGET_FIELD_DISPLAY_NAMES[targetField]}</span></div>
            <div>Type: <span className="text-term-text">{form.mappingType === 'concept' ? 'XBRL Concept' : 'Formula'}</span></div>
            {form.mappingType === 'concept' && (
              <div>Concept: <span className="text-term-text">
                {form.selectedConcept
                  ? `${form.selectedConcept.taxonomy}:${form.selectedConcept.concept}`
                  : '{taxonomy}:{concept}'}
              </span></div>
            )}
            {form.mappingType === 'formula' && (
              <div>Formula: <span className="text-term-text">
                {form.formula || '{formula expression}'}
              </span></div>
            )}
            <div>Scope: <span className="text-term-text">{form.isGlobal ? 'Global' : context.symbol}</span></div>
          </div>
        </div>

        </div>

        <div className="pointer-events-none sticky bottom-[58px] z-10 h-6 bg-gradient-to-t from-term-bg to-transparent" />
        {/* Actions - Always visible at the bottom */}
        <div className="sticky bottom-0 z-20 flex shrink-0 justify-end gap-2 border-t border-term-border-subtle bg-term-bg px-4 py-3">
          <button
            type="button"
            onClick={onClose}
            disabled={isSubmitting}
            className="rounded-md border border-term-border-subtle px-4 py-2 text-sm font-medium text-term-text hover:bg-term-bg-secondary disabled:opacity-50"
          >
            Cancel
          </button>
          <button
            type="submit"
            disabled={isSubmitting || isLoading}
            className="flex min-w-[140px] items-center justify-center gap-2 rounded-md bg-term-text px-4 py-2 text-sm font-medium text-term-bg hover:bg-term-text-hover disabled:opacity-50"
          >
            {isSubmitting ? (
              <>
                <Loader2 className="h-4 w-4 animate-spin" />
                Saving...
              </>
            ) : (
              'Save Mapping'
            )}
          </button>
        </div>
      </form>
    </div>
  );
}

function isIsoDate(value: string | undefined): value is string {
  return Boolean(value && /^\d{4}-\d{2}-\d{2}$/.test(value));
}
