import { useEffect, useState } from 'react';
import { Card } from '../components/Card';
import { Badge } from '../components/Badge';
import { wpApiFetch, useConfig } from '../hooks/useApi';
import { useNotify } from '../hooks/useNotify';
import { DOCUMENT_TEMPLATES } from '@cra-compliance/shared';
import type { DocumentTemplate, DocumentField } from '@cra-compliance/types';

interface GeneratedDocument {
  id: number;
  template_id: string;
  title: string;
  content: string;
  field_values: string;
  created_at: string;
}

export function Documents() {
  const config = useConfig();
  const isPro = config.plan === 'pro';
  const { confirm, toast, NotifyPortal } = useNotify();
  const [savedDocs, setSavedDocs] = useState<GeneratedDocument[]>([]);
  const [activeTemplate, setActiveTemplate] = useState<DocumentTemplate | null>(null);
  const [fieldValues, setFieldValues] = useState<Record<string, string>>({});
  const [generatedContent, setGeneratedContent] = useState<string | null>(null);
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);

  useEffect(() => {
    wpApiFetch<{ data: GeneratedDocument[] }>('documents')
      .then((res) => setSavedDocs(res.data || []))
      .catch(() => {})
      .finally(() => setLoading(false));
  }, []);

  const selectTemplate = (template: DocumentTemplate) => {
    setActiveTemplate(template);
    setGeneratedContent(null);
    setErrors({});
    // Pre-fill with default values
    const defaults: Record<string, string> = {};
    template.fields.forEach((f) => {
      defaults[f.id] = '';
    });
    defaults['current_date'] = new Date().toLocaleDateString('en-GB', {
      year: 'numeric',
      month: 'long',
      day: 'numeric',
    });
    setFieldValues(defaults);
  };

  const validateFields = (): boolean => {
    if (!activeTemplate) return false;

    const newErrors: Record<string, string> = {};

    for (const field of activeTemplate.fields) {
      const value = (fieldValues[field.id] || '').trim();

      if (field.required && !value) {
        newErrors[field.id] = `${field.label} is required`;
        continue;
      }

      if (!value) continue;

      if (field.type === 'email') {
        const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        if (!emailPattern.test(value)) {
          newErrors[field.id] = 'Please enter a valid email address';
        }
      }

      if (field.type === 'url') {
        try {
          const url = new URL(value);
          if (!url.protocol.startsWith('http')) {
            newErrors[field.id] = 'URL must start with http:// or https://';
          }
        } catch {
          newErrors[field.id] = 'Please enter a valid URL (e.g. https://example.com)';
        }
      }
    }

    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };

  const buildContent = (values: Record<string, string>) => {
    if (!activeTemplate) return '';
    let content = activeTemplate.template_content;
    Object.entries(values).forEach(([key, value]) => {
      const label = activeTemplate.fields.find((f) => f.id === key)?.label || key;
      content = content.replace(new RegExp(`\\{\\{${key}\\}\\}`, 'g'), value || `[${label}]`);
    });
    // Replace any remaining unreplaced variables (e.g. current_date)
    content = content.replace(/\{\{(\w+)\}\}/g, (_, k) => values[k] || `[${k}]`);
    return content;
  };

  const liveContent = activeTemplate ? buildContent(fieldValues) : '';

  const generateDocument = () => {
    if (!activeTemplate) return;
    if (!validateFields()) return;
    setGeneratedContent(liveContent);
  };

  const saveDocument = async () => {
    if (!activeTemplate || !generatedContent) return;
    setSaving(true);

    try {
      const res = await wpApiFetch<{ data: GeneratedDocument }>('documents', {
        method: 'POST',
        body: JSON.stringify({
          template_id: activeTemplate.id,
          title: activeTemplate.title,
          content: generatedContent,
          field_values: JSON.stringify(fieldValues),
        }),
      });
      setSavedDocs((prev) => [res.data, ...prev]);
      setActiveTemplate(null);
      setGeneratedContent(null);
      toast({ message: 'Document saved.', type: 'success' });
    } catch {
      toast({ message: 'Failed to save document.', type: 'error' });
    } finally {
      setSaving(false);
    }
  };

  const deleteDocument = async (id: number) => {
    const ok = await confirm({ message: 'Delete this document? This cannot be undone.', danger: true, confirmLabel: 'Delete' });
    if (!ok) return;
    try {
      await wpApiFetch(`documents/${id}`, { method: 'DELETE' });
      setSavedDocs((prev) => prev.filter((d) => d.id !== id));
      toast({ message: 'Document deleted.', type: 'success' });
    } catch {
      toast({ message: 'Failed to delete document.', type: 'error' });
    }
  };

  const copyToClipboard = (content: string) => {
    navigator.clipboard.writeText(content);
  };

  const downloadAsFile = (content: string, title: string, ext: 'txt' | 'md' = 'txt') => {
    const mimeType = ext === 'md' ? 'text/markdown' : 'text/plain';
    const blob = new Blob([content], { type: mimeType });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `${title.replace(/\s+/g, '-').toLowerCase()}.${ext}`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  };

  const downloadAsCycloneDX = () => {
    if (!activeTemplate || activeTemplate.id !== 'sbom') return;
    const v = fieldValues;
    const now = new Date().toISOString();
    const slug = (v['plugin_slug'] || v['plugin_name'] || 'plugin').toLowerCase().replace(/\s+/g, '-');

    const phpDeps = (v['php_dependencies'] || '').split(/[\n,]+/).map(s => s.trim()).filter(Boolean);
    const jsDeps  = (v['js_dependencies']  || '').split(/[\n,]+/).map(s => s.trim()).filter(Boolean);

    const toComponent = (raw: string, type: string) => {
      const match = raw.match(/^(.+?)\s+([\^~>=<\d].*)$/);
      const name    = match ? match[1].trim() : raw;
      const version = match ? match[2].replace(/[\^~>=<]/g, '').trim() : 'unknown';
      return {
        type: 'library',
        'bom-ref': `${name}@${version}`,
        name,
        version,
        purl: `pkg:${type}/${name}@${version}`,
      };
    };

    const cyclonedx = {
      bomFormat: 'CycloneDX',
      specVersion: '1.5',
      serialNumber: `urn:uuid:${('10000000-1000-4000-8000-100000000000').replace(/[018]/g, (c) => (parseInt(c) ^ (Math.random() * 16 >> parseInt(c) / 4)).toString(16))}`,
      version: 1,
      metadata: {
        timestamp: now,
        tools: [{ vendor: 'ResilienceWP', name: 'CRA Compliance Manager', version: '1.2.1' }],
        component: {
          type: 'application',
          'bom-ref': `${slug}@${v['plugin_version'] || '0.0.0'}`,
          name: v['plugin_name'] || '',
          version: v['plugin_version'] || '',
          purl: `pkg:wordpress-plugin/${slug}@${v['plugin_version'] || '0.0.0'}`,
          licenses: [{ license: { id: v['license'] || 'GPL-2.0-or-later' } }],
          supplier: { name: v['org_name'] || '' },
        },
      },
      components: [
        ...phpDeps.map(d => toComponent(d, 'composer')),
        ...jsDeps.map(d => toComponent(d, 'npm')),
      ],
    };

    const blob = new Blob([JSON.stringify(cyclonedx, null, 2)], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `sbom-${slug}-${v['plugin_version'] || '0.0.0'}.cdx.json`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  };

  if (loading) {
    return <div className="cra-loading">Loading documents...</div>;
  }

  // Template selection view
  if (!activeTemplate) {
    return (
      <div className="cra-documents-page">
        <NotifyPortal />
        <div className="cra-page-header">
          <h2>Document Generator</h2>
          <p>
            Generate CRA-compliant documents required for EU Cyber Resilience Act
            conformity. Fill in your details and download.
          </p>
        </div>

        <div className="cra-section">
          <h3>Available Templates</h3>
          <div className="cra-template-grid">
            {DOCUMENT_TEMPLATES.map((template) => {
              const locked = template.premium_only && !isPro;
              return locked ? (
                <a
                  key={template.id}
                  href="https://www.resiliencewp.com/pricing"
                  target="_blank"
                  rel="noopener noreferrer"
                  className="cra-template-card cra-template-card-locked"
                  title="Requires Pro plan"
                >
                  <div className="cra-template-lock">Pro</div>
                  <h4>{template.title}</h4>
                  <p>{template.description}</p>
                  <div className="cra-template-tags">
                    {template.cra_articles.map((article) => (
                      <Badge key={article} variant="neutral" size="sm">
                        {article}
                      </Badge>
                    ))}
                  </div>
                </a>
              ) : (
                <button
                  key={template.id}
                  className="cra-template-card"
                  onClick={() => selectTemplate(template)}
                >
                  <h4>{template.title}</h4>
                  <p>{template.description}</p>
                  <div className="cra-template-tags">
                    {template.cra_articles.map((article) => (
                      <Badge key={article} variant="neutral" size="sm">
                        {article}
                      </Badge>
                    ))}
                  </div>
                </button>
              );
            })}
          </div>
        </div>

        {savedDocs.length > 0 && (
          <div className="cra-section">
            <h3>Your Generated Documents</h3>
            {savedDocs.map((doc) => (
              <Card key={doc.id} className="cra-saved-doc">
                <div className="cra-saved-doc-header">
                  <div>
                    <strong>{doc.title}</strong>
                    <span className="cra-muted" style={{ marginLeft: '8px' }}>
                      {new Date(doc.created_at).toLocaleDateString()}
                    </span>
                  </div>
                  <div className="cra-saved-doc-actions">
                    <button
                      className="cra-btn cra-btn-sm"
                      onClick={() => downloadAsFile(doc.content, doc.title)}
                    >
                      Download
                    </button>
                    <button
                      className="cra-btn cra-btn-sm"
                      onClick={() => copyToClipboard(doc.content)}
                    >
                      Copy
                    </button>
                    <button
                      className="cra-btn cra-btn-sm cra-btn-danger"
                      onClick={() => deleteDocument(doc.id)}
                    >
                      Delete
                    </button>
                  </div>
                </div>
              </Card>
            ))}
          </div>
        )}
      </div>
    );
  }

  // Document generation view
  return (
    <div className="cra-documents-page">
      <NotifyPortal />
      <div className="cra-page-header">
        <button className="cra-btn cra-btn-sm" onClick={() => setActiveTemplate(null)}>
          &larr; Back to Templates
        </button>
        <h2>{activeTemplate.title}</h2>
        <p>{activeTemplate.description}</p>
      </div>

      <div className="cra-doc-generator">
        {/* Form */}
        <Card title="Fill in Your Details">
          <div className="cra-form">
            {activeTemplate.fields.map((field) => (
              <div key={field.id} className="cra-form-field">
                <label htmlFor={field.id}>
                  {field.label}
                  {field.required && <span className="cra-required">*</span>}
                </label>
                {renderField(field, fieldValues[field.id] || '', (value) => {
                  setFieldValues((prev) => ({ ...prev, [field.id]: value }));
                  setGeneratedContent(null);
                  if (errors[field.id]) {
                    setErrors((prev) => {
                      const next = { ...prev };
                      delete next[field.id];
                      return next;
                    });
                  }
                }, errors[field.id])}
                {errors[field.id] && (
                  <span className="cra-field-error">{errors[field.id]}</span>
                )}
              </div>
            ))}
            <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
              <button className="cra-btn cra-btn-primary" onClick={generateDocument}>
                Finalize Document
              </button>
              {activeTemplate.id === 'security-txt' ? (
                <button
                  className="cra-btn cra-btn-sm"
                  onClick={() => downloadAsFile(liveContent, 'security', 'txt')}
                >
                  Download .txt
                </button>
              ) : (
                <>
                  <button
                    className="cra-btn cra-btn-sm"
                    onClick={() => downloadAsFile(liveContent, activeTemplate.title, 'md')}
                  >
                    Download .md
                  </button>
                  <button
                    className="cra-btn cra-btn-sm"
                    onClick={() => downloadAsFile(liveContent, activeTemplate.title)}
                  >
                    Download .txt
                  </button>
                </>
              )}
              {activeTemplate.id === 'sbom' && (
                <button
                  className="cra-btn cra-btn-sm"
                  onClick={downloadAsCycloneDX}
                  title="Machine-readable CycloneDX 1.5 JSON — compatible with OWASP Dependency-Track, GitHub, and other tooling"
                >
                  Download CycloneDX JSON
                </button>
              )}
              <button
                className="cra-btn cra-btn-sm"
                onClick={() => copyToClipboard(liveContent)}
              >
                Copy to Clipboard
              </button>
            </div>
          </div>
        </Card>

        {/* Live Preview - always visible */}
        <Card
          title="Document Preview"
          actions={
            generatedContent ? (
              <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
                <button
                  className="cra-btn cra-btn-sm cra-btn-primary"
                  onClick={saveDocument}
                  disabled={saving}
                >
                  {saving ? 'Saving...' : 'Save Document'}
                </button>
              </div>
            ) : undefined
          }
        >
          <div className="cra-doc-preview">
            <pre>{generatedContent || liveContent}</pre>
          </div>
        </Card>
      </div>
    </div>
  );
}

function renderField(
  field: DocumentField,
  value: string,
  onChange: (value: string) => void,
  error?: string
) {
  const cls = `cra-input${error ? ' cra-input-error' : ''}`;

  if (field.type === 'textarea') {
    return (
      <textarea
        id={field.id}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        placeholder={field.placeholder}
        rows={3}
        className={cls}
      />
    );
  }

  if (field.type === 'select' && field.options) {
    return (
      <select
        id={field.id}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        className={cls}
      >
        <option value="">{field.placeholder}</option>
        {field.options.map((opt) => (
          <option key={opt} value={opt}>
            {opt}
          </option>
        ))}
      </select>
    );
  }

  return (
    <input
      id={field.id}
      type={field.type}
      value={value}
      onChange={(e) => onChange(e.target.value)}
      placeholder={field.placeholder}
      className={cls}
    />
  );
}
