'use client';

import React, { useState, useEffect } from 'react';
import { FiUploadCloud, FiX, FiMail, FiBellOff, FiFile, FiTrash2 } from 'react-icons/fi';
import toast from 'react-hot-toast';
import { uploadDocument, getUsersForRoles } from '@/lib/api/documents.api';
import { CATEGORY_META } from '@/lib/api/mappers/documents.mappers';
import type { RoleMember } from '@/lib/api/types/documents.types';
import styles from './UploadDocumentModal.module.css';

interface Role {
  id: number;
  name: string;
}

interface Props {
  isOpen: boolean;
  onClose: () => void;
  onUploaded: () => void;
  roles: Role[];
}

export default function UploadDocumentModal({
  isOpen,
  onClose,
  onUploaded,
  roles,
}: Props) {
  const [files, setFiles] = useState<File[]>([]);
  const [title, setTitle] = useState('');
  const [category, setCategory] = useState<string>(Object.keys(CATEGORY_META)[0]);
  const [description, setDescription] = useState('');
  const [selectedRoleIds, setSelectedRoleIds] = useState<Set<number>>(new Set());
  const [roleMembers, setRoleMembers] = useState<RoleMember[]>([]);
  const [loadingMembers, setLoadingMembers] = useState(false);
  const [skippedUserIds, setSkippedUserIds] = useState<Set<number>>(new Set());
  const [requireOtp, setRequireOtp] = useState(true);
  const [allowDownload, setAllowDownload] = useState(true);
  const [password, setPassword] = useState('');
  const [expiryDate, setExpiryDate] = useState('');
  const [uploading, setUploading] = useState(false);
  const [progress, setProgress] = useState(0);

  const toggleRole = (id: number) => {
    setSelectedRoleIds((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  };

  useEffect(() => {
    if (!isOpen || selectedRoleIds.size === 0) {
      setRoleMembers([]);
      return;
    }
    let cancelled = false;
    setLoadingMembers(true);
    getUsersForRoles(Array.from(selectedRoleIds))
      .then((members) => {
        if (cancelled) return;
        setRoleMembers(members);
        setSkippedUserIds((prev) => {
          const validIds = new Set(members.map((m) => m.id));
          const next = new Set<number>();
          prev.forEach((id) => {
            if (validIds.has(id)) next.add(id);
          });
          return next;
        });
      })
      .catch(() => {
        if (!cancelled) toast.error('Could not load role members');
      })
      .finally(() => {
        if (!cancelled) setLoadingMembers(false);
      });
    return () => {
      cancelled = true;
    };
  }, [isOpen, Array.from(selectedRoleIds).sort().join(',')]);

  const toggleSkip = (userId: number) => {
    setSkippedUserIds((prev) => {
      const next = new Set(prev);
      if (next.has(userId)) next.delete(userId);
      else next.add(userId);
      return next;
    });
  };

  const handleFiles = (newFiles: FileList | null) => {
    if (!newFiles) return;
    const fileArray = Array.from(newFiles);
    setFiles((prev) => [...prev, ...fileArray]);
    
    if (!title && fileArray.length > 0) {
      const base = fileArray[0].name.replace(/\.[^/.]+$/, '').replace(/[_-]+/g, ' ');
      setTitle(base);
    }
  };

  const removeFile = (index: number) => {
    setFiles((prev) => prev.filter((_, i) => i !== index));
  };

  const getFileIcon = (fileName: string) => {
    const ext = fileName.split('.').pop()?.toLowerCase();
    if (['pdf'].includes(ext || '')) return '📄';
    if (['doc', 'docx'].includes(ext || '')) return '📝';
    if (['xls', 'xlsx'].includes(ext || '')) return '📊';
    if (['jpg', 'jpeg', 'png', 'gif', 'svg'].includes(ext || '')) return '🖼️';
    if (['zip', 'rar', '7z'].includes(ext || '')) return '📦';
    return '📎';
  };

  const reset = () => {
    setFiles([]);
    setTitle('');
    setDescription('');
    setSelectedRoleIds(new Set());
    setRoleMembers([]);
    setSkippedUserIds(new Set());
    setRequireOtp(true);
    setAllowDownload(true);
    setPassword('');
    setExpiryDate('');
    setProgress(0);
  };

  const handleSubmit = async () => {
    if (files.length === 0) return toast.error('Please select at least one file');
    if (!title.trim()) return toast.error('Please enter a title');
    if (selectedRoleIds.size === 0)
      return toast.error('Assign the document to at least one role');

    setUploading(true);
    setProgress(0);
    try {
      const notifyUserIds = roleMembers
        .filter((m) => !skippedUserIds.has(m.id))
        .map((m) => m.id);

      for (let i = 0; i < files.length; i++) {
        const file = files[i];
        const docTitle = files.length === 1 ? title.trim() : `${title.trim()} - ${file.name}`;
        
        await uploadDocument(
          {
            file,
            title: docTitle,
            category,
            description: description.trim() || undefined,
            role_ids: Array.from(selectedRoleIds),
            notify_user_ids: notifyUserIds,
            require_otp: requireOtp,
            allow_download: allowDownload,
            password: password || undefined,
            expiry_date: expiryDate || undefined,
          },
          (pct) => {
            const baseProgress = (i / files.length) * 100;
            const currentProgress = (pct / files.length);
            setProgress(Math.round(baseProgress + currentProgress));
          },
        );
      }

      toast.success(`${files.length} document${files.length > 1 ? 's' : ''} uploaded`);
      reset();
      onUploaded();
      onClose();
    } catch (err: any) {
      toast.error(err.message || 'Upload failed');
    } finally {
      setUploading(false);
      setProgress(0);
    }
  };

  if (!isOpen) return null;

  return (
    <div className={styles.overlay} onClick={uploading ? undefined : onClose}>
      <div className={styles.modal} onClick={(e) => e.stopPropagation()}>
        {/* ── Top Bar ── */}
        <div className={styles.topbar}>
          <div className={styles.topbarLeft}>
            <button
              type="button"
              className={styles.backBtn}
              onClick={onClose}
              disabled={uploading}
              aria-label="Back"
            >
              ←
            </button>
            <div>
              <h1 className={styles.pageTitle}>Upload & Assign Documents</h1>
              <p className={styles.pageSub}>
                Assign to roles — everyone in those roles gets access automatically
              </p>
            </div>
          </div>
          <div className={styles.topbarActions}>
            <button
              type="button"
              className={styles.btnGhost}
              onClick={onClose}
              disabled={uploading}
            >
              Cancel
            </button>
            <button
              type="button"
              className={styles.btnPrimary}
              onClick={handleSubmit}
              disabled={uploading || files.length === 0}
            >
              {uploading ? `Uploading ${Math.round(progress)}%` : `Upload ${files.length} File${files.length > 1 ? 's' : ''} →`}
            </button>
          </div>
        </div>

        {/* ── Content ── */}
        <div className={styles.content}>
          {/* ── Card 1: Document Details ── */}
          <div className={styles.card}>
            <div className={styles.cardHead}>
              <div className={styles.cardHeadLeft}>
                <span className={styles.stepBadge}>📄</span>
                <div>
                  <p className={styles.cardTitle}>Document Details</p>
                  <p className={styles.cardHint}>
                    Upload documents and provide basic information
                  </p>
                </div>
              </div>
              <div className={styles.fileCount}>
                {files.length > 0 && (
                  <span className={styles.fileCountBadge}>{files.length} file{files.length > 1 ? 's' : ''} selected</span>
                )}
              </div>
            </div>
            <div className={styles.cardBody}>
              <div className={styles.grid}>
                {/* File Dropzone - Full Width */}
                <div className={styles.full}>
                  <label className={`${styles.label} ${styles.req}`}>Documents</label>
                  <label className={styles.dropzone}>
                    <input
                      type="file"
                      multiple
                      onChange={(e) => handleFiles(e.target.files)}
                      style={{ display: 'none' }}
                      disabled={uploading}
                      accept=".pdf,.doc,.docx,.xls,.xlsx,.jpg,.jpeg,.png,.gif,.zip,.rar,.7z"
                    />
                    <div className={styles.dropzoneIcon}>
                      <FiUploadCloud size={32} />
                    </div>
                    <div className={styles.dropzoneText}>
                      Drop files here or <span className={styles.browseText}>browse</span>
                    </div>
                    <div className={styles.dropzoneHint}>
                      PDF, Word, Excel, images, ZIP — up to 500 MB each · Multiple files supported
                    </div>
                  </label>

                  {/* File List */}
                  {files.length > 0 && (
                    <div className={styles.fileList}>
                      {files.map((file, index) => (
                        <div key={index} className={styles.fileItem}>
                          <span className={styles.fileIcon}>{getFileIcon(file.name)}</span>
                          <div className={styles.fileInfo}>
                            <div className={styles.fileName}>{file.name}</div>
                            <div className={styles.fileSize}>
                              {(file.size / (1024 * 1024)).toFixed(2)} MB
                            </div>
                          </div>
                          {!uploading && (
                            <button
                              type="button"
                              className={styles.fileRemove}
                              onClick={() => removeFile(index)}
                              aria-label="Remove file"
                            >
                              <FiTrash2 size={14} />
                            </button>
                          )}
                        </div>
                      ))}
                    </div>
                  )}
                </div>

                {/* Title - Half Width */}
                <div className={styles.half}>
                  <label className={`${styles.label} ${styles.req}`}>Title</label>
                  <input
                    type="text"
                    value={title}
                    onChange={(e) => setTitle(e.target.value)}
                    placeholder="e.g. ISO 9001 Quality Manual"
                    className={styles.input}
                    disabled={uploading}
                  />
                  {files.length > 1 && (
                    <p className={styles.helperText}>
                      Each file will be titled: "{title} - filename"
                    </p>
                  )}
                </div>

                {/* Category - Half Width */}
                <div className={styles.half}>
                  <label className={styles.label}>Category</label>
                  <select
                    value={category}
                    onChange={(e) => setCategory(e.target.value)}
                    className={styles.select}
                    disabled={uploading}
                  >
                    {Object.keys(CATEGORY_META).map((k) => (
                      <option key={k} value={k}>
                        {CATEGORY_META[k].icon} {CATEGORY_META[k].label}
                      </option>
                    ))}
                  </select>
                </div>

                {/* Description - Full Width */}
                <div className={styles.full}>
                  <label className={styles.label}>Description</label>
                  <textarea
                    value={description}
                    onChange={(e) => setDescription(e.target.value)}
                    placeholder="Short note about these documents"
                    className={styles.textarea}
                    rows={3}
                    disabled={uploading}
                  />
                </div>
              </div>
            </div>
          </div>

          {/* ── Card 2: Assignment & Security ── */}
          <div className={styles.card}>
            <div className={styles.cardHead}>
              <div className={styles.cardHeadLeft}>
                <span className={styles.stepBadge}>🔐</span>
                <div>
                  <p className={styles.cardTitle}>Assignment & Security</p>
                  <p className={styles.cardHint}>
                    Assign to roles and configure access controls
                  </p>
                </div>
              </div>
            </div>
            <div className={styles.cardBody}>
              <div className={styles.grid}>
                {/* Roles - Full Width */}
                <div className={styles.full}>
                  <label className={`${styles.label} ${styles.req}`}>Assign to Roles</label>
                  <div className={styles.roleChips}>
                    {roles.length === 0 ? (
                      <span className={styles.emptyState}>No roles available</span>
                    ) : (
                      roles.map((r) => {
                        const active = selectedRoleIds.has(r.id);
                        return (
                          <button
                            key={r.id}
                            onClick={() => !uploading && toggleRole(r.id)}
                            className={`${styles.roleChip} ${active ? styles.roleChipActive : ''}`}
                            disabled={uploading}
                          >
                            {r.name}
                            {active && <span className={styles.roleCheck}>✓</span>}
                          </button>
                        );
                      })
                    )}
                  </div>
                </div>

                {/* Notify Checklist */}
                {selectedRoleIds.size > 0 && (
                  <div className={styles.full}>
                    <label className={styles.label}>
                      Notify by Email
                      {roleMembers.length > 0 && (
                        <span className={styles.notifyCount}>
                          ({roleMembers.length - skippedUserIds.size} of {roleMembers.length})
                        </span>
                      )}
                    </label>
                    <p className={styles.helperText}>
                      Everyone below gets the document either way — uncheck anyone you don't
                      want to email about it.
                    </p>

                    {loadingMembers ? (
                      <div className={styles.loadingState}>Loading role members…</div>
                    ) : roleMembers.length === 0 ? (
                      <div className={styles.emptyState}>No users found in the selected role(s)</div>
                    ) : (
                      <div className={styles.memberList}>
                        {roleMembers.map((m) => {
                          const skipped = skippedUserIds.has(m.id);
                          return (
                            <div
                              key={m.id}
                              onClick={() => !uploading && toggleSkip(m.id)}
                              className={`${styles.memberItem} ${skipped ? styles.memberSkipped : ''}`}
                            >
                              <input
                                type="checkbox"
                                checked={!skipped}
                                onChange={() => toggleSkip(m.id)}
                                disabled={uploading}
                                className={styles.memberCheckbox}
                              />
                              <div className={styles.memberInfo}>
                                <div className={styles.memberName}>{m.name}</div>
                                <div className={styles.memberEmail}>{m.email}</div>
                              </div>
                              {skipped ? (
                                <FiBellOff size={14} className={styles.memberIconSkipped} />
                              ) : (
                                <FiMail size={14} className={styles.memberIconActive} />
                              )}
                            </div>
                          );
                        })}
                      </div>
                    )}
                  </div>
                )}

                {/* Security Settings - Full Width */}
                <div className={styles.full}>
                  <label className={styles.label}>Security Settings</label>
                  <div className={styles.switchGrid}>
                    <div className={styles.switchRow}>
                      <SwitchToggle
                        on={requireOtp}
                        onChange={() => setRequireOtp(!requireOtp)}
                        disabled={uploading}
                      />
                      <span className={styles.switchLabel}>Require email OTP to open</span>
                    </div>

                    <div className={styles.switchRow}>
                      <SwitchToggle
                        on={!!password}
                        onChange={() => setPassword(password ? '' : 'secret123')}
                        disabled={uploading}
                      />
                      <span className={styles.switchLabel}>Require password</span>
                    </div>

                    {password !== '' && (
                      <input
                        type="password"
                        value={password}
                        onChange={(e) => setPassword(e.target.value)}
                        className={styles.input}
                        placeholder="Enter password"
                        disabled={uploading}
                      />
                    )}

                    <div className={styles.switchRow}>
                      <SwitchToggle
                        on={allowDownload}
                        onChange={() => setAllowDownload(!allowDownload)}
                        disabled={uploading}
                      />
                      <span className={styles.switchLabel}>Allow download (off = view-only)</span>
                    </div>
                  </div>
                </div>

                {/* Expiry Date - Full Width */}
                <div className={styles.full}>
                  <label className={styles.label}>Expiry Date</label>
                  <input
                    type="date"
                    value={expiryDate}
                    onChange={(e) => setExpiryDate(e.target.value)}
                    className={styles.input}
                    disabled={uploading}
                    min={new Date().toISOString().split('T')[0]}
                  />
                  <p className={styles.helperText}>Leave empty for no expiry</p>
                </div>
              </div>
            </div>
          </div>

          {/* ── Progress ── */}
          {uploading && (
            <div className={styles.progressContainer}>
              <div className={styles.progressTrack}>
                <div
                  className={styles.progressFill}
                  style={{ width: `${progress}%` }}
                />
              </div>
              <span className={styles.progressLabel}>{progress}%</span>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

// ─── Switch Toggle ────────────────────────────────────────────────────────
function SwitchToggle({
  on,
  onChange,
  disabled,
}: {
  on: boolean;
  onChange: () => void;
  disabled?: boolean;
}) {
  return (
    <button
      type="button"
      onClick={disabled ? undefined : onChange}
      className={`${styles.switch} ${on ? styles.switchOn : ''}`}
      disabled={disabled}
      aria-pressed={on}
    >
      <span className={`${styles.switchThumb} ${on ? styles.switchThumbOn : ''}`} />
    </button>
  );
}