/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-argument */
'use client';

import { useEffect, useState, useCallback } from 'react';
import { X, Loader2 } from 'lucide-react';
import { useCrmApi } from '../context';
import type { EntityConfig, CustomFieldDef, PipelineData } from '../types';

interface EntityFormDialogProps {
  config: EntityConfig;
  open: boolean;
  onClose: () => void;
  onSaved: () => void;
  mode: 'create' | 'edit';
  initialData?: Record<string, any>;
  entityId?: string;
}

const inputClass =
  'w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500/30 bg-white text-gray-900';

export function EntityFormDialog({
  config,
  open,
  onClose,
  onSaved,
  mode,
  initialData,
  entityId,
}: EntityFormDialogProps) {
  const api = useCrmApi();
  const [saving, setSaving] = useState(false);
  const [values, setValues] = useState<Record<string, any>>({});
  const [customFields, setCustomFields] = useState<CustomFieldDef[]>([]);
  const [customValues, setCustomValues] = useState<Record<string, any>>({});
  const [pipelines, setPipelines] = useState<PipelineData[]>([]);
  const [staffList, setStaffList] = useState<{ id: string; name: string }[]>([]);

  const fetchMeta = useCallback(async () => {
    try {
      const promises: Promise<any>[] = [];

      // Fetch custom fields
      if (config.features.customFields) {
        promises.push(api.get<CustomFieldDef[]>(`/crm/fields?entityType=${config.entityType}`));
      } else {
        promises.push(Promise.resolve([]));
      }

      // Fetch pipelines
      if (config.features.pipelines) {
        promises.push(api.get<PipelineData[]>(`/crm/pipelines?entityType=${config.entityType}`));
      } else {
        promises.push(Promise.resolve([]));
      }

      // Fetch staff for assignee
      promises.push(
        api
          .get<{ id: string; firstName: string; lastName: string }[]>('/users?role=manager')
          .catch(() => []),
      );

      const [cf, pl, staff] = await Promise.all(promises);
      setCustomFields((cf as CustomFieldDef[]) || []);
      setPipelines((pl as PipelineData[]) || []);
      const staffData = (staff || []) as { id: string; firstName: string; lastName: string }[];
      setStaffList(
        staffData.map((s) => ({
          id: s.id,
          name: `${s.firstName} ${s.lastName}`,
        })),
      );
    } catch {
      //
    }
  }, [api, config]);

  useEffect(() => {
    if (open) {
      void fetchMeta();
      if (mode === 'edit' && initialData) {
        const vals: Record<string, any> = {};
        for (const field of config.systemFields) {
          if (initialData[field.key] !== undefined) {
            vals[field.key] = initialData[field.key];
          }
        }
        // Also copy other known keys
        for (const key of ['pipelineId', 'stageId', 'assigneeId']) {
          if (initialData[key] !== undefined) vals[key] = initialData[key];
        }
        setValues(vals);
        setCustomValues(initialData.customFieldValues || {});
      } else {
        setValues({});
        setCustomValues({});
      }
    }
  }, [open, mode, initialData, config, fetchMeta]);

  const setVal = (key: string, value: any) => {
    setValues((prev) => ({ ...prev, [key]: value }));
  };

  const setCfVal = (fieldName: string, value: any) => {
    setCustomValues((prev) => ({ ...prev, [fieldName]: value }));
  };

  const handleSave = async () => {
    setSaving(true);
    try {
      const data: Record<string, any> = { ...values };

      // Add custom fields
      if (Object.keys(customValues).length > 0) {
        data.customFieldValues = customValues;
      }

      if (mode === 'edit' && entityId) {
        await api.patch(`${config.apiPrefix}/${entityId}`, data);
      } else {
        await api.post(config.apiPrefix, data);
      }
      onSaved();
      onClose();
    } catch (err: unknown) {
      alert(err instanceof Error ? err.message : 'Ошибка сохранения');
    } finally {
      setSaving(false);
    }
  };

  if (!open) return null;

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center">
      <div className="absolute inset-0 bg-black/40" onClick={onClose} />
      <div className="relative bg-white rounded-2xl shadow-xl w-full max-w-lg mx-4 max-h-[85vh] flex flex-col">
        {/* Header */}
        <div className="flex items-center justify-between px-6 py-4 border-b border-gray-100">
          <h2 className="text-lg font-semibold text-gray-900">
            {mode === 'edit'
              ? `Редактировать ${config.label.singular.toLowerCase()}`
              : `Новая ${config.label.singular.toLowerCase()}`}
          </h2>
          <button onClick={onClose} className="p-1 rounded-lg hover:bg-gray-100 transition-colors">
            <X className="h-5 w-5 text-gray-400" />
          </button>
        </div>

        {/* Body */}
        <div className="flex-1 overflow-y-auto px-6 py-4 space-y-4">
          {/* System fields */}
          {config.systemFields
            .filter((f) => f.defaultVisible !== false)
            .map((field) => (
              <div key={field.key}>
                <label className="block text-sm font-medium text-gray-700 mb-1">
                  {field.label}
                </label>
                {renderFieldInput(field, values[field.key], (v) => setVal(field.key, v))}
              </div>
            ))}

          {/* Pipeline selector */}
          {config.features.pipelines && pipelines.length > 0 && mode === 'create' && (
            <div>
              <label className="block text-sm font-medium text-gray-700 mb-1">Воронка</label>
              <select
                value={values.pipelineId || pipelines[0]?.id || ''}
                onChange={(e) => setVal('pipelineId', e.target.value)}
                className={inputClass}
              >
                {pipelines.map((p) => (
                  <option key={p.id} value={p.id}>
                    {p.name}
                  </option>
                ))}
              </select>
            </div>
          )}

          {/* Assignee */}
          {staffList.length > 0 && (
            <div>
              <label className="block text-sm font-medium text-gray-700 mb-1">Ответственный</label>
              <select
                value={values.assigneeId || ''}
                onChange={(e) => setVal('assigneeId', e.target.value || undefined)}
                className={inputClass}
              >
                <option value="">— Не назначен —</option>
                {staffList.map((s) => (
                  <option key={s.id} value={s.id}>
                    {s.name}
                  </option>
                ))}
              </select>
            </div>
          )}

          {/* Custom fields */}
          {customFields.length > 0 && (
            <>
              <div className="border-t border-gray-100 pt-4 mt-4">
                <h3 className="text-xs font-medium text-gray-500 mb-3 uppercase">
                  Дополнительные поля
                </h3>
              </div>
              {customFields.map((cf) => (
                <div key={cf.id}>
                  <label className="block text-sm font-medium text-gray-700 mb-1">
                    {cf.name}
                    {cf.isRequired && <span className="text-red-500 ml-0.5">*</span>}
                  </label>
                  {renderCustomFieldInput(cf, customValues[cf.fieldName], (v) =>
                    setCfVal(cf.fieldName, v),
                  )}
                  {cf.description && (
                    <p className="text-xs text-gray-400 mt-0.5">{cf.description}</p>
                  )}
                </div>
              ))}
            </>
          )}
        </div>

        {/* Footer */}
        <div className="flex items-center justify-end gap-3 px-6 py-4 border-t border-gray-100">
          <button
            onClick={onClose}
            className="px-4 py-2 text-sm text-gray-500 hover:text-gray-700 transition-colors"
          >
            Отмена
          </button>
          <button
            onClick={() => void handleSave()}
            disabled={saving}
            className="flex items-center gap-2 px-4 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50 transition-colors"
          >
            {saving && <Loader2 className="h-4 w-4 animate-spin" />}
            {saving ? 'Сохранение...' : 'Сохранить'}
          </button>
        </div>
      </div>
    </div>
  );
}

function renderFieldInput(
  field: { key: string; type: string; enumOptions?: { value: string; label: string }[] },
  value: any,
  onChange: (v: any) => void,
) {
  switch (field.type) {
    case 'currency':
    case 'number':
      return (
        <input
          type="number"
          value={value ?? ''}
          onChange={(e) => onChange(e.target.value ? Number(e.target.value) : undefined)}
          className={inputClass}
        />
      );
    case 'date':
      return (
        <input
          type="date"
          value={value ?? ''}
          onChange={(e) => onChange(e.target.value)}
          className={inputClass}
        />
      );
    case 'enum':
      return (
        <select
          value={value ?? ''}
          onChange={(e) => onChange(e.target.value)}
          className={inputClass}
        >
          <option value="">—</option>
          {(field.enumOptions || []).map((opt) => (
            <option key={opt.value} value={opt.value}>
              {opt.label}
            </option>
          ))}
        </select>
      );
    case 'phone':
    case 'email':
    case 'string':
    default:
      return (
        <input
          type={field.type === 'email' ? 'email' : field.type === 'phone' ? 'tel' : 'text'}
          value={value ?? ''}
          onChange={(e) => onChange(e.target.value)}
          className={inputClass}
        />
      );
  }
}

function renderCustomFieldInput(cf: CustomFieldDef, value: any, onChange: (v: any) => void) {
  switch (cf.type) {
    case 'INTEGER':
    case 'FLOAT':
      return (
        <input
          type="number"
          step={cf.type === 'FLOAT' ? '0.01' : '1'}
          value={value ?? ''}
          onChange={(e) => onChange(e.target.value ? Number(e.target.value) : undefined)}
          className={inputClass}
        />
      );
    case 'BOOLEAN':
      return (
        <label className="flex items-center gap-2 cursor-pointer">
          <input
            type="checkbox"
            checked={!!value}
            onChange={(e) => onChange(e.target.checked)}
            className="rounded border-gray-300"
          />
          <span className="text-sm text-gray-700">{cf.name}</span>
        </label>
      );
    case 'DATE':
      return (
        <input
          type="date"
          value={value ?? ''}
          onChange={(e) => onChange(e.target.value)}
          className={inputClass}
        />
      );
    case 'DATETIME':
      return (
        <input
          type="datetime-local"
          value={value ?? ''}
          onChange={(e) => onChange(e.target.value)}
          className={inputClass}
        />
      );
    case 'LIST':
      return (
        <select
          value={value ?? ''}
          onChange={(e) => onChange(e.target.value)}
          className={inputClass}
        >
          <option value="">—</option>
          {(cf.listOptions || []).map((opt) => (
            <option key={opt} value={opt}>
              {opt}
            </option>
          ))}
        </select>
      );
    case 'STRING':
    default:
      return (
        <input
          type="text"
          value={value ?? ''}
          onChange={(e) => onChange(e.target.value)}
          className={inputClass}
        />
      );
  }
}
