/**
 * LinkEditModal Component
 *
 * Modal for editing a link's properties: label, type, URL/page, open in new tab.
 * Uses React Portal to render at document body level for proper fixed positioning.
 */

'use client';

import { useState, useEffect } from 'react';
import { createPortal } from 'react-dom';
import { LinkItem } from './LinkEditorContent';
import {
  normalizeUrl,
  extractLabelFromUrl,
  isValidSafeUrl as isValidSafeUrlBase,
} from '@/lib/cms/link-validation-client';

interface PageOption {
  id: string;
  slug: string;
  title: string;
}

interface PdfAsset {
  id: string;
  url: string;
  filename: string;
}

interface LinkEditModalProps {
  link: LinkItem;
  pages: PageOption[];
  onSave: (link: LinkItem) => void;
  onCancel: () => void;
}

/**
 * Wrapper for URL validation that returns error messages for UI display
 */
const validateUrl = (url: string): { valid: boolean; error?: string } => {
  const normalized = normalizeUrl(url);

  // Allow relative URLs
  if (normalized.startsWith('/') || normalized.startsWith('#')) {
    return { valid: true };
  }

  if (isValidSafeUrlBase(url)) {
    return { valid: true };
  }

  // Provide user-friendly error messages
  // Check for control characters using charCodeAt (ESLint-compliant)
  const hasControlChars = url.split('').some((char) => {
    const code = char.charCodeAt(0);
    return (code >= 0 && code <= 31) || code === 127;
  });
  if (hasControlChars) {
    return { valid: false, error: 'URL contains invalid characters' };
  }

  return {
    valid: false,
    error: 'Please enter a valid URL (e.g., google.com or https://example.com)',
  };
};

export function LinkEditModal({ link, pages, onSave, onCancel }: LinkEditModalProps) {
  const [label, setLabel] = useState(link.label);
  const [linkType, setLinkType] = useState<'page' | 'external' | 'pdf'>(link.linkType);
  const [pageId, setPageId] = useState(link.pageId || '');
  const [externalUrl, setExternalUrl] = useState(link.externalUrl || '');
  const [openInNewTab, setOpenInNewTab] = useState(link.openInNewTab);
  const [error, setError] = useState<string | null>(null);
  // Track if label was auto-generated (so we can update it when URL changes)
  const [labelWasAutoGenerated, setLabelWasAutoGenerated] = useState(
    link.label === 'New Link' || link.label === ''
  );

  const [pdfAssets, setPdfAssets] = useState<PdfAsset[]>([]);
  const [loadingPdfs, setLoadingPdfs] = useState(false);
  const [selectedPdfUrl, setSelectedPdfUrl] = useState(
    link.linkType === 'pdf' ? link.externalUrl || '' : ''
  );

  useEffect(() => {
    if (linkType !== 'pdf') return;
    setLoadingPdfs(true);
    fetch('/api/media')
      .then((r) => {
        if (!r.ok) throw new Error(`Failed to load documents (${r.status})`);
        return r.json();
      })
      .then((data) => {
        const pdfs = (data.myImages || []).filter(
          (asset: { mimeType: string }) => asset.mimeType === 'application/pdf'
        );
        setPdfAssets(pdfs);
      })
      .catch(() => setError('Could not load PDF documents. Please try again.'))
      .finally(() => setLoadingPdfs(false));
  }, [linkType]);

  const handlePdfChange = (pdfUrl: string) => {
    setSelectedPdfUrl(pdfUrl);
    const selectedPdf = pdfAssets.find((p) => `/api/documents/${p.id}` === pdfUrl);
    if (selectedPdf && (labelWasAutoGenerated || !label || label === 'New Link')) {
      setLabel(selectedPdf.filename.replace(/\.pdf$/i, '').replace(/[-_]/g, ' '));
      setLabelWasAutoGenerated(true);
    }
    setOpenInNewTab(true);
  };

  // Handle page selection - auto-populate label from page title
  const handlePageChange = (newPageId: string) => {
    setPageId(newPageId);
    // Auto-populate label from page title if label is empty or was auto-generated
    const selectedPage = pages.find((p) => p.id === newPageId);
    if (selectedPage && (labelWasAutoGenerated || !label || label === 'New Link')) {
      setLabel(selectedPage.title);
      setLabelWasAutoGenerated(true);
    }
  };

  // Handle URL change - auto-generate label from domain
  const handleUrlBlur = () => {
    if (!externalUrl.trim()) return;

    // Only auto-label if current label is empty, default, or was auto-generated
    if (labelWasAutoGenerated || !label || label === 'New Link') {
      const extractedLabel = extractLabelFromUrl(externalUrl);
      if (extractedLabel) {
        setLabel(extractedLabel);
        setLabelWasAutoGenerated(true);
      }
    }
  };

  // When user manually edits label, mark it as not auto-generated
  const handleLabelChange = (newLabel: string) => {
    setLabel(newLabel);
    setLabelWasAutoGenerated(false);
  };

  const handleSave = () => {
    // Validation
    if (!label.trim()) {
      setError('Label is required');
      return;
    }
    if (label.length > 50) {
      setError('Label must be 50 characters or less');
      return;
    }
    if (linkType === 'page' && !pageId) {
      setError('Please select a page');
      return;
    }
    if (linkType === 'pdf' && !selectedPdfUrl) {
      setError('Please select a PDF');
      return;
    }

    // Normalize URL (add https:// if needed)
    const normalizedUrl = linkType === 'external' ? normalizeUrl(externalUrl) : null;

    if (linkType === 'external') {
      if (!externalUrl.trim()) {
        setError('Please enter a URL');
        return;
      }
      // Validate URL format and protocol security (uses normalized URL)
      const urlValidation = validateUrl(externalUrl);
      if (!urlValidation.valid) {
        setError(urlValidation.error!);
        return;
      }
    }

    const selectedPage = pages.find((p) => p.id === pageId);

    onSave({
      ...link,
      label: label.trim(),
      linkType,
      pageId: linkType === 'page' ? pageId : null,
      pageSlug: linkType === 'page' && selectedPage ? selectedPage.slug : null,
      pageTitle: linkType === 'page' && selectedPage ? selectedPage.title : null,
      externalUrl: linkType === 'external' ? normalizedUrl : linkType === 'pdf' ? selectedPdfUrl : null,
      openInNewTab,
    });
  };

  // Only render on client (portal requires document.body)
  if (typeof window === 'undefined') return null;

  const modalContent = (
    <div
      style={{
        position: 'fixed',
        top: 0,
        left: 0,
        right: 0,
        bottom: 0,
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        zIndex: 9999,
        padding: '24px',
        backgroundColor: 'rgba(0, 0, 0, 0.75)',
        backdropFilter: 'blur(8px)',
      }}
      onClick={(e) => e.target === e.currentTarget && onCancel()}
    >
      <div
        style={{
          width: '100%',
          maxWidth: '28rem',
          padding: '24px',
          borderRadius: '12px',
          background: 'linear-gradient(145deg, rgba(30, 41, 59, 0.95), rgba(15, 23, 42, 0.98))',
          border: '1px solid rgba(148, 163, 184, 0.15)',
          boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.5)',
        }}
        onClick={(e) => e.stopPropagation()}
      >
        <h2 className="text-xl font-bold mb-4" style={{ color: '#f8fafc' }}>
          Edit Link
        </h2>

        {error && (
          <div className="mb-4 p-2 bg-red-900/50 border border-red-700 rounded text-red-200 text-sm">
            {error}
          </div>
        )}

        <div style={{ display: 'flex', flexDirection: 'column', gap: '24px' }}>
          {/* Link Type */}
          <div>
            <label
              style={{
                display: 'block',
                fontSize: '0.875rem',
                fontWeight: 500,
                color: '#e2e8f0',
                marginBottom: '10px',
              }}
            >
              Link Type
            </label>
            <select
              value={linkType}
              onChange={(e) => {
                const newType = e.target.value as 'page' | 'external' | 'pdf';
                setLinkType(newType);
                if (newType === 'pdf') setOpenInNewTab(true);
              }}
              style={{
                width: '100%',
                padding: '14px 16px',
                background: 'rgba(15, 23, 42, 0.8)',
                border: '1px solid rgba(148, 163, 184, 0.3)',
                borderRadius: '10px',
                color: '#f8fafc',
                fontSize: '0.9rem',
              }}
            >
              <option value="external">External URL</option>
              <option value="page">Internal Page</option>
              <option value="pdf">Internal PDF</option>
            </select>
          </div>

          {/* Page Selector or URL Input */}
          <div style={{ minHeight: '80px' }}>
            {linkType === 'page' ? (
              <div>
                <label
                  style={{
                    display: 'block',
                    fontSize: '0.875rem',
                    fontWeight: 500,
                    color: '#e2e8f0',
                    marginBottom: '10px',
                  }}
                >
                  Select Page
                </label>
                <select
                  value={pageId}
                  onChange={(e) => handlePageChange(e.target.value)}
                  style={{
                    width: '100%',
                    padding: '14px 16px',
                    background: 'rgba(15, 23, 42, 0.8)',
                    border: '1px solid rgba(148, 163, 184, 0.3)',
                    borderRadius: '10px',
                    color: '#f8fafc',
                    fontSize: '0.9rem',
                  }}
                >
                  <option value="">-- Choose a page --</option>
                  {pages.map((page) => (
                    <option key={page.id} value={page.id}>
                      {page.title} (/{page.slug})
                    </option>
                  ))}
                </select>
                {pages.length === 0 && (
                  <p style={{ fontSize: '0.8rem', color: '#94a3b8', marginTop: '10px' }}>
                    No custom pages found. Create pages in the CMS first.
                  </p>
                )}
              </div>
            ) : linkType === 'pdf' ? (
              <div>
                <label
                  style={{
                    display: 'block',
                    fontSize: '0.875rem',
                    fontWeight: 500,
                    color: '#e2e8f0',
                    marginBottom: '10px',
                  }}
                >
                  Select PDF
                </label>
                <select
                  value={selectedPdfUrl}
                  onChange={(e) => handlePdfChange(e.target.value)}
                  disabled={loadingPdfs}
                  style={{
                    width: '100%',
                    padding: '14px 16px',
                    background: 'rgba(15, 23, 42, 0.8)',
                    border: '1px solid rgba(148, 163, 184, 0.3)',
                    borderRadius: '10px',
                    color: '#f8fafc',
                    fontSize: '0.9rem',
                    opacity: loadingPdfs ? 0.5 : 1,
                  }}
                >
                  <option value="">
                    {loadingPdfs ? 'Loading documents...' : '-- Choose a PDF --'}
                  </option>
                  {pdfAssets.map((pdf) => (
                    <option key={pdf.id} value={`/api/documents/${pdf.id}`}>
                      {pdf.filename}
                    </option>
                  ))}
                </select>
                {pdfAssets.length === 0 && !loadingPdfs && (
                  <p style={{ fontSize: '0.8rem', color: '#94a3b8', marginTop: '10px' }}>
                    No PDFs found. Upload documents in the Media Library first.
                  </p>
                )}
              </div>
            ) : (
              <div>
                <label
                  style={{
                    display: 'block',
                    fontSize: '0.875rem',
                    fontWeight: 500,
                    color: '#e2e8f0',
                    marginBottom: '10px',
                  }}
                >
                  External URL
                </label>
                <input
                  type="text"
                  value={externalUrl}
                  onChange={(e) => setExternalUrl(e.target.value)}
                  onBlur={handleUrlBlur}
                  placeholder="google.com or https://..."
                  maxLength={500}
                  style={{
                    width: '100%',
                    padding: '14px 16px',
                    background: 'rgba(15, 23, 42, 0.8)',
                    border: '1px solid rgba(148, 163, 184, 0.3)',
                    borderRadius: '10px',
                    color: '#f8fafc',
                    fontSize: '0.9rem',
                    boxSizing: 'border-box',
                  }}
                />
              </div>
            )}
          </div>

          {/* Label */}
          <div>
            <label
              style={{
                display: 'block',
                fontSize: '0.875rem',
                fontWeight: 500,
                color: '#e2e8f0',
                marginBottom: '10px',
              }}
            >
              Label
            </label>
            <input
              type="text"
              value={label}
              onChange={(e) => handleLabelChange(e.target.value)}
              maxLength={50}
              style={{
                width: '100%',
                padding: '14px 16px',
                background: 'rgba(15, 23, 42, 0.8)',
                border: '1px solid rgba(148, 163, 184, 0.3)',
                borderRadius: '10px',
                color: '#f8fafc',
                fontSize: '0.9rem',
                boxSizing: 'border-box',
              }}
            />
            <p style={{ marginTop: '6px', fontSize: '0.8rem', color: '#64748b' }}>
              {label.length}/50 characters
            </p>
          </div>

          {/* Open in New Tab */}
          <div>
            <label
              style={{
                display: 'flex',
                alignItems: 'center',
                gap: '14px',
                fontSize: '0.9rem',
                color: '#e2e8f0',
                cursor: 'pointer',
              }}
            >
              <input
                type="checkbox"
                checked={openInNewTab}
                onChange={(e) => setOpenInNewTab(e.target.checked)}
                style={{ width: '18px', height: '18px' }}
              />
              Open in new tab
            </label>
          </div>
        </div>

        {/* Actions - Style Guide compliant */}
        <div
          style={{
            display: 'flex',
            gap: '8px',
            justifyContent: 'flex-end',
            paddingTop: '24px',
            marginTop: '24px',
            borderTop: '1px solid rgba(148, 163, 184, 0.15)',
          }}
        >
          <button
            onClick={onCancel}
            type="button"
            style={{
              padding: '12px 24px',
              background: 'transparent',
              border: '1px solid #38bdf8',
              borderRadius: '8px',
              color: '#38bdf8',
              cursor: 'pointer',
              fontSize: '16px',
              fontWeight: 600,
              transition: 'background 0.2s ease',
            }}
            onMouseEnter={(e) => (e.currentTarget.style.background = 'rgba(56, 189, 248, 0.1)')}
            onMouseLeave={(e) => (e.currentTarget.style.background = 'transparent')}
          >
            Cancel
          </button>
          <button
            onClick={handleSave}
            type="button"
            style={{
              padding: '12px 24px',
              background: '#38bdf8',
              border: 'none',
              borderRadius: '8px',
              color: '#0f172a',
              cursor: 'pointer',
              fontSize: '16px',
              fontWeight: 600,
              transition: 'transform 0.2s ease, box-shadow 0.2s ease',
              boxShadow: '0 8px 20px -12px rgba(56, 189, 248, 0.6)',
            }}
            onMouseEnter={(e) => {
              e.currentTarget.style.transform = 'translateY(-2px)';
              e.currentTarget.style.boxShadow = '0 16px 40px -15px rgba(56, 189, 248, 0.95)';
            }}
            onMouseLeave={(e) => {
              e.currentTarget.style.transform = 'translateY(0)';
              e.currentTarget.style.boxShadow = '0 8px 20px -12px rgba(56, 189, 248, 0.6)';
            }}
          >
            Save Changes
          </button>
        </div>
      </div>
    </div>
  );

  // Use portal to render at document body level (avoids CSS containment issues)
  return createPortal(modalContent, document.body);
}
