import { useEffect, useState, useCallback } from 'react';
import { Modal, Form, Select, DatePicker, Input, Spin, message, Row, Col, Button, Space, Divider, Tag } from 'antd';
import { PlusOutlined, EyeOutlined, SearchOutlined } from '@ant-design/icons';
import dayjs from 'dayjs';
import { posteingangApi } from '../api/posteingang';
import type { DocumentRequirement, PosteingangDocument, Kontonummer } from '../api/posteingang';
import { clientsApi } from '../api/inbox';
import type { Client } from '../api/inbox';
import { paperlessApi } from '../api/paperless';
import type { PaperlessDocType, PaperlessCorrespondent, PaperlessTag } from '../api/paperless';
import { getEnv } from '../utils/env';
import { AuthIframe, openAuthUrl } from '../utils/auth-resource';
import DocumentSearchModal from './DocumentSearchModal';

const { Option } = Select;

interface Props {
  documentId: number | null;
  document: PosteingangDocument | null;
  open: boolean;
  onClose: (next?: boolean) => void;
  onSave: () => void;
  isPosteingang?: boolean;
  hasNextDocument?: boolean;
}

export default function DocumentEditModal({ documentId, document, open, onClose, onSave, isPosteingang = true, hasNextDocument = true }: Props) {
  const [form] = Form.useForm();
  
  const [loading, setLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  
  const [clients, setClients] = useState<Client[]>([]);
  const [documentTypes, setDocumentTypes] = useState<PaperlessDocType[]>([]);
  const [correspondents, setCorrespondents] = useState<PaperlessCorrespondent[]>([]);
  const [requirements, setRequirements] = useState<DocumentRequirement[]>([]);

  // Tags: alle Tags + als Steuertags markierte IDs; bearbeitbar sind nur Inhaltstags
  const [allTags, setAllTags] = useState<PaperlessTag[]>([]);
  const [steuertagIds, setSteuertagIds] = useState<number[]>([]);
  const contentTags = allTags.filter(t => !steuertagIds.includes(t.id));

  const [kontonummerMissing, setKontonummerMissing] = useState<{ correspondentId: number, nummer: string } | null>(null);
  const [docTitles, setDocTitles] = useState<Record<number, string>>({});
  const [searchModalOpen, setSearchModalOpen] = useState<{ field: string, reqId: number } | null>(null);

  // Kontonummer state
  const [kontonummern, setKontonummern] = useState<Kontonummer[]>([]);
  const [kontonummernLoading, setKontonummernLoading] = useState(false);
  const [newKontonummer, setNewKontonummer] = useState('');

  const selectedCorrespondent = Form.useWatch('correspondent', form);

  const loadKontonummern = useCallback(async (correspondentId: number) => {
    setKontonummernLoading(true);
    try {
      const data = await posteingangApi.getKontonummern(correspondentId);
      setKontonummern(data);
    } catch {
      setKontonummern([]);
    } finally {
      setKontonummernLoading(false);
    }
  }, []);

  useEffect(() => {
    if (selectedCorrespondent) {
      loadKontonummern(selectedCorrespondent);
    } else {
      setKontonummern([]);
    }
  }, [selectedCorrespondent, loadKontonummern]);

  const handleAddKontonummer = async () => {
    const trimmed = newKontonummer.trim();
    if (!trimmed || !selectedCorrespondent) return;
    try {
      await posteingangApi.createKontonummer({ correspondentId: selectedCorrespondent, nummer: trimmed });
      message.success(`Kontonummer "${trimmed}" hinzugefügt.`);
      setNewKontonummer('');
      await loadKontonummern(selectedCorrespondent);
      form.setFieldValue('cf_5', trimmed);
    } catch {
      message.error('Kontonummer konnte nicht angelegt werden.');
    }
  };

  useEffect(() => {
    const resolveLinkTitles = async () => {
      const linkFields = requirements.filter(r => r.feldTyp === 'documentlink');
      for (const req of linkFields) {
        const fieldName = req.isCustomField ? `cf_${req.customFieldIndex}` : req.feldId;
        const val = form.getFieldValue(fieldName);
        if (val && !docTitles[val]) {
          try {
            const d = await paperlessApi.getDocument(val);
            setDocTitles(prev => ({ ...prev, [val]: d.title }));
          } catch (e) {
             // Handle or ignore
          }
        }
      }
    };
    if (open && requirements.length > 0) {
      resolveLinkTitles();
    }
  }, [requirements, open]); // Removed docTitles to avoid loop, we check val existence anyway

  useEffect(() => {
    if (open) {
      loadInitialData();
    } else {
      form.resetFields();
      setRequirements([]);
      setKontonummerMissing(null);
      setKontonummern([]);
      setNewKontonummer('');
    }
  }, [open]);

  useEffect(() => {
    if (open && document) {
        
        let customFieldsObj: any = {};
        if (document.customFields) {
           document.customFields.forEach(cf => {
               customFieldsObj[`cf_${cf.field}`] = cf.value;
           });
        }

        form.setFieldsValue({
            mandant: document.owner,
            documentType: document.documentType,
            correspondent: document.correspondent,
            title: document.title,
            asn: document.asn,
            belegdatum: document.created ? dayjs(document.created) : null,
            eingangsdatum: customFieldsObj['cf_9'] ? dayjs(customFieldsObj['cf_9']) : (document.added ? dayjs(document.added) : null),
            ...customFieldsObj,
        });

        if (document.documentType) {
            fetchRequirements(document.documentType);
        }
    }
  }, [document, form, open]);

  // Tags getrennt setzen: nur Inhaltstags (Steuertags werden nicht angezeigt/bearbeitet)
  useEffect(() => {
    if (open && document) {
        const contentTagIds = (document.tags || []).filter(id => !steuertagIds.includes(id));
        form.setFieldValue('tags', contentTagIds);
    }
  }, [document, open, steuertagIds, form]);

  const ensureCorrespondentInList = async (correspondentId: number | null | undefined) => {
    if (!correspondentId) return;
    
    setCorrespondents(prev => {
        const exists = prev.some(c => Number(c.id) === Number(correspondentId));
        if (!exists) {
            // We need to fetch it. But we can't easily do it inside setCorrespondents.
            // So we'll do it outside.
            return prev;
        }
        return prev;
    });

    const exists = correspondents.some(c => Number(c.id) === Number(correspondentId));
    if (!exists) {
        try {
            const currentCorr = await paperlessApi.getCorrespondent(correspondentId);
            if (currentCorr) {
                setCorrespondents(prev => {
                    if (prev.some(c => Number(c.id) === Number(currentCorr.id))) return prev;
                    return [...prev, currentCorr];
                });
            }
        } catch (e) {
            console.error("Fehler beim Laden des zugewiesenen Absenders:", e);
        }
    }
  };

  useEffect(() => {
    if (open && document?.correspondent) {
        ensureCorrespondentInList(document.correspondent);
    }
  }, [document?.correspondent, open]);

  const loadInitialData = async () => {
    setLoading(true);
    try {
      const [clientsData, docTypesData, correspondentsData, tagsData, steuertagData] = await Promise.all([
        clientsApi.getMyClients(),
        paperlessApi.getDocumentTypes(),
        paperlessApi.getCorrespondents(),
        paperlessApi.getTags(),
        paperlessApi.getSteuertagIds(),
      ]);
      setClients(clientsData);
      setDocumentTypes(docTypesData);
      setCorrespondents(correspondentsData);
      setAllTags(tagsData);
      setSteuertagIds(steuertagData);
      
      // If document is already there, ensure its correspondent is in the list
      if (document?.correspondent) {
          const exists = correspondentsData.some(c => Number(c.id) === Number(document.correspondent));
          if (!exists) {
              const currentCorr = await paperlessApi.getCorrespondent(document.correspondent);
              if (currentCorr) {
                  setCorrespondents([...correspondentsData, currentCorr]);
              }
          }
      }
    } catch (e) {
      message.error("Fehler beim Laden der Stammdaten.");
    } finally {
      setLoading(false);
    }
  };

  const fetchRequirements = async (docType: number) => {
    try {
      const reqs = await posteingangApi.getRequirements(docType, isPosteingang);
      setRequirements(reqs);
    } catch (e) {
      message.error("Fehler beim Laden der Pflichtfelder.");
    }
  };

  const [fetchingCorrespondents, setFetchingCorrespondents] = useState(false);
  const [searchTimeout, setSearchTimeout] = useState<any>(null);
  
  const handleCorrespondentSearch = async (value: string) => {
    if (searchTimeout) clearTimeout(searchTimeout);
    
    setSearchTimeout(setTimeout(async () => {
      setFetchingCorrespondents(true);
      try {
        const data = await paperlessApi.getCorrespondents(value);
        setCorrespondents(data);
      } catch (e) {
        message.error("Absender konnten nicht geladen werden.");
      } finally {
        setFetchingCorrespondents(false);
      }
    }, 500));
  };

  const handleDocumentTypeChange = (value: number) => {
    fetchRequirements(value);
  };

  const handleSaveDocument = async (values: any, isNext: boolean = false) => {
    // Collect custom fields into an array
    const customFieldsObj: any = {};
    Object.keys(values).forEach(key => {
        if (key.startsWith('cf_')) {
            const fieldId = parseInt(key.replace('cf_', ''), 10);
            customFieldsObj[fieldId] = values[key];
        }
    });

    if (values.eingangsdatum) {
        customFieldsObj[9] = values.eingangsdatum.format('YYYY-MM-DD');
    } else {
        customFieldsObj[9] = null;
    }

    const payload = {
        mandant: values.mandant,
        documentType: values.documentType,
        correspondent: values.correspondent,
        title: values.title,
        date: values.belegdatum ? values.belegdatum.format('YYYY-MM-DD') : null,
        tags: values.tags || [],
        customFields: customFieldsObj,
    };

    setSaving(true);
    try {
      await posteingangApi.updateDocument(documentId!, payload);
      message.success("Dokument erfolgreich aktualisiert.");
      onSave();
      onClose(isNext);
    } catch (e) {
      message.error("Fehler beim Speichern des Dokuments.");
    } finally {
      setSaving(false);
    }
  };

  const handleSubmit = async (isNext: boolean = false) => {
    try {
        const values = await form.validateFields();
        
        // Kontonummer Logic
        const kontonummerReq = requirements.find(r => r.customFieldIndex === 5);
        if (kontonummerReq && values[`cf_5`] && values.correspondent) {
            const kNummer = values[`cf_5`];
            const knData = await posteingangApi.getKontonummern(values.correspondent);
            const exists = knData.some(k => k.Nummer === kNummer);
            
            if (!exists) {
                // Prompt user to save kontonummer
                setKontonummerMissing({ correspondentId: values.correspondent, nummer: kNummer });
                return; // Stop saving, wait for confirmation
            }
        }

        await handleSaveDocument(values, isNext);
    } catch (e) {
        // Validation failed
        console.error("Form validation failed:", e);
    }
  };

  const confirmKontonummerSave = async (shouldSave: boolean, isNext: boolean = false) => {
      if (shouldSave && kontonummerMissing) {
          try {
              await posteingangApi.createKontonummer(kontonummerMissing);
              message.success("Kontonummer hinterlegt.");
          } catch (e) {
              message.error("Fehler beim Speichern der Kontonummer.");
          }
      }
      setKontonummerMissing(null);
      
      const values = form.getFieldsValue();
      await handleSaveDocument(values, isNext);
  };

  const handleSelectLink = (doc: any) => {
    if (searchModalOpen) {
      form.setFieldValue(searchModalOpen.field, doc.id);
      setDocTitles(prev => ({ ...prev, [doc.id]: doc.title }));
      setSearchModalOpen(null);
      form.validateFields([searchModalOpen.field]);
    }
  };

  if (documentId === null) return null;

  return (
    <>
      <Modal
        title={`Dokument bearbeiten (${document?.title || ''})`}
        open={open && !kontonummerMissing}
        onCancel={() => onClose(false)}
        width={1400}
        style={{ top: 20 }}
        footer={
           hasNextDocument ? [
               <Button key="cancel" onClick={() => onClose(false)}>Abbrechen</Button>,
               <Button key="save" type="primary" loading={saving} onClick={() => handleSubmit(false)}>Speichern</Button>,
               <Button key="saveNext" type="primary" ghost loading={saving} onClick={() => handleSubmit(true)}>Speichern & Nächstes</Button>
           ] : [
               <Button key="cancel" onClick={() => onClose(false)}>Abbrechen</Button>,
               <Button key="save" type="primary" loading={saving} onClick={() => handleSubmit(false)}>Speichern</Button>
           ]
        }
      >
        <Spin spinning={loading}>
            <Row gutter={16} style={{ height: '75vh', overflow: 'hidden' }}>
                <Col span={10} style={{ overflowY: 'auto', paddingRight: '1rem', borderRight: '1px solid #f0f0f0' }}>
                    <Form form={form} layout="vertical" disabled={saving}>
                        
                        <Form.Item name="mandant" label="Mandant" rules={[{ required: true, message: 'Wähle einen Mandanten' }]}>
                            <Select showSearch optionFilterProp="children" allowClear>
                                {clients.map(c => (
                                    <Option key={c.Id} value={c.PaperlessUserId}>{c.Name}</Option>
                                ))}
                            </Select>
                        </Form.Item>

                        <Form.Item name="documentType" label="Dokumentart" rules={[{ required: true, message: 'Wähle eine Dokumentart' }]}>
                            <Select showSearch optionFilterProp="children" onChange={handleDocumentTypeChange}>
                                {documentTypes.map(d => (
                                    <Option key={d.id} value={d.id}>{d.name}</Option>
                                ))}
                            </Select>
                        </Form.Item>

                        <Form.Item name="belegdatum" label="Belegdatum">
                            <DatePicker style={{ width: '100%' }} format="DD.MM.YYYY" />
                        </Form.Item>

                        <Form.Item name="eingangsdatum" label="Eingangsdatum">
                            <DatePicker style={{ width: '100%' }} format="DD.MM.YYYY" />
                        </Form.Item>

                        <Form.Item name="tags" label="Tags">
                            <Select
                                mode="multiple"
                                allowClear
                                showSearch
                                optionFilterProp="label"
                                placeholder="Tags auswählen"
                                options={contentTags.map(t => ({ value: t.id, label: t.name }))}
                                tagRender={({ value, closable, onClose }) => {
                                    const tag = allTags.find(t => t.id === value);
                                    return (
                                        <Tag
                                            color={tag?.color}
                                            style={{ color: tag?.text_color, marginInlineEnd: 4 }}
                                            closable={closable}
                                            onClose={onClose}
                                        >
                                            {tag?.name ?? value}
                                        </Tag>
                                    );
                                }}
                                optionRender={(opt) => {
                                    const tag = contentTags.find(t => t.id === opt.value);
                                    return tag ? (
                                        <Tag color={tag.color} style={{ color: tag.text_color }}>{tag.name}</Tag>
                                    ) : opt.label;
                                }}
                            />
                        </Form.Item>

                        {/* Rendering dynamic requirements based on DocumentType */}
                        {requirements.map(req => {
                            if (req.feldId === '2' || (req.isCustomField && req.customFieldIndex === 9)) {
                                return null;
                            }

                            let inputElement = <Input />;

                            if (req.isCustomField && req.customFieldIndex === 5) {
                                // Kontonummer — Select mit Möglichkeit neue anzulegen
                                inputElement = (
                                    <Select
                                        showSearch
                                        allowClear
                                        optionFilterProp="children"
                                        placeholder={!selectedCorrespondent ? 'Bitte zuerst einen Absender wählen' : 'Kontonummer wählen'}
                                        disabled={!selectedCorrespondent}
                                        loading={kontonummernLoading}
                                        notFoundContent={kontonummernLoading ? <Spin size="small" /> : 'Keine Kontonummern vorhanden'}
                                        dropdownRender={(menu) => (
                                            <>
                                                {menu}
                                                <Divider style={{ margin: '8px 0' }} />
                                                <div style={{ display: 'flex', gap: 8, padding: '0 8px 8px' }}>
                                                    <Input
                                                        placeholder="Neue Kontonummer"
                                                        value={newKontonummer}
                                                        onChange={(e) => setNewKontonummer(e.target.value)}
                                                        onKeyDown={(e) => e.stopPropagation()}
                                                    />
                                                    <Button
                                                        type="text"
                                                        icon={<PlusOutlined />}
                                                        onClick={handleAddKontonummer}
                                                        disabled={!newKontonummer.trim()}
                                                    >
                                                        Anlegen
                                                    </Button>
                                                </div>
                                            </>
                                        )}
                                    >
                                        {kontonummern.map((k) => (
                                            <Option key={k.KontonummerId ?? k.Nummer} value={k.Nummer}>
                                                {k.Nummer}
                                            </Option>
                                        ))}
                                    </Select>
                                );
                            } else if (req.feldId === '1') {
                                inputElement = (
                                    <Select 
                                        showSearch 
                                        filterOption={false}
                                        onSearch={handleCorrespondentSearch}
                                        notFoundContent={fetchingCorrespondents ? <Spin size="small" /> : null}
                                    >
                                        {correspondents.map(c => (
                                            <Option key={c.id} value={c.id}>{c.name}</Option>
                                        ))}
                                    </Select>
                                );
                            } else if (req.feldTyp === 'date') {
                                inputElement = <DatePicker style={{ width: '100%' }} format="DD.MM.YYYY" />;
                            } else if (req.feldTyp === 'select' && req.fieldOptions) {
                                inputElement = (
                                    <Select showSearch optionFilterProp="children">
                                        {req.fieldOptions.map(opt => (
                                            <Option key={opt.id} value={opt.id}>{opt.label}</Option>
                                        ))}
                                    </Select>
                                );
                            } else if (req.feldTyp === 'documentlink') {
                                const fieldName = req.isCustomField ? `cf_${req.customFieldIndex}` : 
                                                 req.feldId === '1' ? 'correspondent' :
                                                 req.feldId === '2' ? 'belegdatum' :
                                                 req.feldId === '3' ? 'asn' :
                                                 req.feldId === '5' ? 'title' : req.feldId;
                                
                                const currentId = form.getFieldValue(fieldName);
                                
                                inputElement = (
                                    <Input 
                                        readOnly 
                                        placeholder="Klicken zum Suchen..."
                                        value={currentId ? (docTitles[currentId] || `Dokument #${currentId}`) : ''}
                                        onClick={() => setSearchModalOpen({ field: fieldName, reqId: req.id })}
                                        suffix={
                                            <Space>
                                                {currentId && (
                                                    <Button 
                                                        type="text" 
                                                        size="small" 
                                                        icon={<EyeOutlined />} 
                                                        onClick={(e) => {
                                                            e.stopPropagation();
                                                            openAuthUrl(`${getEnv('VITE_API_URL')}/api/paperless/inbox/pdf/${currentId}`);
                                                        }}
                                                    />
                                                )}
                                                <Button 
                                                    type="text" 
                                                    size="small" 
                                                    icon={<SearchOutlined />} 
                                                    onClick={(e) => {
                                                        e.stopPropagation();
                                                        setSearchModalOpen({ field: fieldName, reqId: req.id });
                                                    }}
                                                />
                                            </Space>
                                        }
                                    />
                                );
                            }

                            const name = req.isCustomField ? `cf_${req.customFieldIndex}` : 
                                         req.feldId === '1' ? 'correspondent' :
                                         req.feldId === '2' ? 'belegdatum' :
                                         req.feldId === '3' ? 'asn' :
                                         req.feldId === '5' ? 'title' : req.feldId;

                            return (
                                <Form.Item 
                                    key={req.id} 
                                    name={name} 
                                    label={req.feldName} 
                                    rules={[{ required: req.required, message: `${req.feldName} ist ein Pflichtfeld` }]}
                                    tooltip={req.hinweis}
                                >
                                    {inputElement}
                                </Form.Item>
                            );
                        })}
                    </Form>
                </Col>
                <Col span={14} style={{ height: '100%' }}>
                    <AuthIframe
                      src={`${getEnv('VITE_API_URL')}/api/paperless/inbox/pdf/${documentId}#toolbar=0`}
                      style={{ width: '100%', height: '100%' }}
                      title="PDF Preview"
                    />
                </Col>
            </Row>
        </Spin>
      </Modal>

      {/* Kontonummer Dialog */}
      <Modal
        title="Neue Kontonummer hinterlegen?"
        open={!!kontonummerMissing}
        onCancel={() => confirmKontonummerSave(false)}
        onOk={() => confirmKontonummerSave(true)}
        okText="Hinterlegen"
        cancelText="Nein, nur Speichern"
      >
         <p>Die Kontonummer <b>{kontonummerMissing?.nummer}</b> ist bei diesem Absender noch nicht hinterlegt.</p>
         <p>Möchtest du sie dem Absender fest zuordnen?</p>
      </Modal>

      <DocumentSearchModal
        open={!!searchModalOpen}
        onCancel={() => setSearchModalOpen(null)}
        onSelect={handleSelectLink}
      />
    </>
  );
}
