import React, { useState, useEffect } from 'react';
import { useNavigate, Link } from 'react-router-dom';
import axiosInstance from '../../../utils/axiosConfig';
import { TICKETS_URL, TICKETS_TYPE_URL } from '../../../utils/config';
import SuccessPopup from '../../common/SuccessPopup';
import ErrorPopup from '../../common/ErrorPopup';
import { useScrollToError } from '../../../hooks/useScrollToError';
import { getUserIdFromToken } from '../../../utils/authUtils';
import './styles/RaiseTicket.css';

const SUBJECT_MAX = 120;
const DESCRIPTION_MIN = 20;
const DESCRIPTION_MAX = 2000;
const MAX_ATTACHMENTS = 5;
const MAX_FILE_SIZE_MB = 10;
const MAX_FILE_SIZE = MAX_FILE_SIZE_MB * 1024 * 1024;
const ACCEPT_MEDIA = 'image/*,video/*,.pdf';

const RaiseTicket = () => {
  const navigate = useNavigate();
  const [formData, setFormData] = useState({
    subject: '',
    ticket_type_id: '',
    description: '',
    recipient_email: 'eframeinterns@gmail.com'
  });
  const [ticketTypes, setTicketTypes] = useState([]);
  const [loading, setLoading] = useState(false);
  const [fetchingData, setFetchingData] = useState(true);
  const [error, setError] = useState(null);
  const [showPopup, setShowPopup] = useState(false);
  const [popupMessage, setPopupMessage] = useState('');
  const [showTips, setShowTips] = useState(false);
  const [showClearConfirm, setShowClearConfirm] = useState(false);
  const [touched, setTouched] = useState({ subject: false, description: false });
  const [attachments, setAttachments] = useState([]);
  const [attachmentError, setAttachmentError] = useState(null);

  useScrollToError(error);

  useEffect(() => {
    const fetchTypes = async () => {
      try {
        setFetchingData(true);
        const res = await axiosInstance.get(TICKETS_TYPE_URL);
        setTicketTypes(res.data.data || []);
      } catch (err) {
        console.error('Error fetching ticket types:', err);
        setError('Failed to load ticket types.');
      } finally {
        setFetchingData(false);
      }
    };
    fetchTypes();
  }, []);

  const handleChange = (e) => {
    const { name, value } = e.target;
    if (name === 'subject' && value.length > SUBJECT_MAX) return;
    if (name === 'description' && value.length > DESCRIPTION_MAX) return;
    setFormData((prev) => ({ ...prev, [name]: value }));
    setError(null);
  };

  const handleBlur = (e) => {
    setTouched((prev) => ({ ...prev, [e.target.name]: true }));
  };

  const formatFileSize = (bytes) => {
    if (bytes < 1024) return bytes + ' B';
    if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
    return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
  };

  const handleFileChange = (e) => {
    setAttachmentError(null);
    const files = Array.from(e.target.files || []);
    if (files.length === 0) return;
    const currentCount = attachments.length;
    if (currentCount + files.length > MAX_ATTACHMENTS) {
      setAttachmentError(`You can attach at most ${MAX_ATTACHMENTS} files.`);
      e.target.value = '';
      return;
    }
    const oversized = files.filter((f) => f.size > MAX_FILE_SIZE);
    if (oversized.length > 0) {
      setAttachmentError(`Some files exceed ${MAX_FILE_SIZE_MB} MB. Please choose smaller files.`);
      e.target.value = '';
      return;
    }
    setAttachments((prev) => [...prev, ...files].slice(0, MAX_ATTACHMENTS));
    e.target.value = '';
  };

  const removeAttachment = (index) => {
    setAttachments((prev) => prev.filter((_, i) => i !== index));
    setAttachmentError(null);
  };

  const subjectError = touched.subject && formData.subject.length > 0 && formData.subject.length < 3;
  const descriptionError = touched.description && formData.description.length > 0 && formData.description.length < DESCRIPTION_MIN;
  const descriptionWarn = formData.description.length >= DESCRIPTION_MIN && formData.description.length < 40;

  const canSubmit =
    formData.ticket_type_id &&
    formData.description?.trim().length >= DESCRIPTION_MIN &&
    !subjectError &&
    !descriptionError;

  const handleSubmit = async (e) => {
    e.preventDefault();
    setError(null);
    const userId = getUserIdFromToken();
    if (!userId) {
      setError('Session expired. Please log in again.');
      return;
    }
    if (!canSubmit) {
      setError('Please complete all required fields. Issue description must be at least ' + DESCRIPTION_MIN + ' characters.');
      return;
    }
    setLoading(true);
    try {
      const hasAttachments = attachments.length > 0;
      if (hasAttachments) {
        const formDataToSend = new FormData();
        formDataToSend.append('user_id', userId);
        formDataToSend.append('ticket_type_id', Number(formData.ticket_type_id));
        formDataToSend.append('subject', formData.subject.trim() || 'Support Request');
        formDataToSend.append('description', formData.description.trim());
        if (formData.recipient_email?.trim()) {
          formDataToSend.append('recipient_email', formData.recipient_email.trim());
        }
        attachments.forEach((file) => formDataToSend.append('attachments', file));
        const res = await axiosInstance.post(TICKETS_URL, formDataToSend, {
          headers: { 'Content-Type': 'multipart/form-data' }
        });
        if (res.data.success) {
          setPopupMessage(
            res.data.message ||
              (res.data.data?.email?.sent
                ? 'Ticket raised successfully. A notification email with your attachments has been sent to the receiver.'
                : 'Ticket raised successfully.')
          );
          setShowPopup(true);
          setFormData({ subject: '', ticket_type_id: '', description: '', recipient_email: 'eframeinterns@gmail.com' });
          setTouched({ subject: false, description: false });
          setAttachments([]);
        } else {
          setError(res.data.message || 'Failed to create ticket.');
        }
      } else {
        const payload = {
          user_id: userId,
          ticket_type_id: Number(formData.ticket_type_id),
          subject: formData.subject.trim() || 'Support Request',
          description: formData.description.trim(),
          recipient_email: formData.recipient_email.trim() || undefined
        };
        const res = await axiosInstance.post(TICKETS_URL, payload);
        if (res.data.success) {
          setPopupMessage(
            res.data.message ||
              (res.data.data?.email?.sent
                ? 'Ticket raised successfully. A notification email has been sent to the receiver.'
                : 'Ticket raised successfully.')
          );
          setShowPopup(true);
          setFormData({ subject: '', ticket_type_id: '', description: '', recipient_email: 'eframeinterns@gmail.com' });
          setTouched({ subject: false, description: false });
        } else {
          setError(res.data.message || 'Failed to create ticket.');
        }
      }
    } catch (err) {
      setError(err.response?.data?.message || 'Failed to raise ticket. Please try again.');
    } finally {
      setLoading(false);
    }
  };

  const handleClearForm = () => {
    setFormData({ subject: '', ticket_type_id: '', description: '', recipient_email: 'eframeinterns@gmail.com' });
    setTouched({ subject: false, description: false });
    setAttachments([]);
    setAttachmentError(null);
    setError(null);
    setShowClearConfirm(false);
  };

  const handlePopupClose = () => {
    setShowPopup(false);
    navigate('/tickets');
  };

  if (fetchingData) {
    return (
      <div className="raise-ticket-page">
        <div className="raise-ticket-loading-wrap">
          <div className="raise-ticket-spinner" aria-hidden="true" />
          <p className="raise-ticket-loading-text">Loading ticket types...</p>
        </div>
      </div>
    );
  }

  return (
    <div className="raise-ticket-page">
      <nav className="raise-ticket-breadcrumb" aria-label="Breadcrumb">
        <Link to="/tickets" className="raise-ticket-breadcrumb-link">Tickets</Link>
        <span className="raise-ticket-breadcrumb-sep">/</span>
        <span className="raise-ticket-breadcrumb-current">Raise Ticket</span>
      </nav>

      <header className="raise-ticket-header">
        <div className="raise-ticket-header-icon" aria-hidden="true">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
            <path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z" />
            <polyline points="14 2 14 8 20 8" />
            <line x1="16" y1="13" x2="8" y2="13" />
            <line x1="16" y1="17" x2="8" y2="17" />
            <line x1="10" y1="9" x2="8" y2="9" />
          </svg>
        </div>
        <h1>Raise a Ticket</h1>
        <p className="raise-ticket-subtitle">
          Describe your issue clearly. A notification email will be sent to the receiver with the form details.
        </p>
      </header>

      <div className="raise-ticket-tips-toggle">
        <button
          type="button"
          className="raise-ticket-tips-btn"
          onClick={() => setShowTips(!showTips)}
          aria-expanded={showTips}
          aria-controls="raise-ticket-tips-content"
        >
          <span className="raise-ticket-tips-btn-icon">{showTips ? '−' : '+'}</span>
          Tips for a good ticket description
        </button>
        <div id="raise-ticket-tips-content" className={`raise-ticket-tips-content ${showTips ? 'is-open' : ''}`} hidden={!showTips}>
          <ul>
            <li>Include what you were doing when the issue occurred.</li>
            <li>Mention any error messages or screenshots if relevant.</li>
            <li>Specify environment (e.g. browser, device) when applicable.</li>
            <li>Keep the subject short and descriptive; add detail in the description.</li>
          </ul>
        </div>
      </div>

      <form className="raise-ticket-form" onSubmit={handleSubmit} noValidate>
        {error && (
          <div className="raise-ticket-error" role="alert">
            <span className="raise-ticket-error-icon" aria-hidden="true">!</span>
            {error}
          </div>
        )}

        <div className="raise-ticket-form-grid">
          <div className="form-group form-group-full">
            <label htmlFor="subject">Subject</label>
            <input
              id="subject"
              name="subject"
              type="text"
              value={formData.subject}
              onChange={handleChange}
              onBlur={handleBlur}
              placeholder="Brief subject of the issue (e.g. Login error on Chrome)"
              maxLength={SUBJECT_MAX}
              aria-describedby="subject-hint subject-count"
              aria-invalid={subjectError}
              className={subjectError ? 'input-error' : ''}
            />
            <div id="subject-hint" className="form-hint">
              Optional. A clear subject helps us route your ticket faster.
            </div>
            <div id="subject-count" className="form-char-count" aria-live="polite">
              {formData.subject.length}/{SUBJECT_MAX}
            </div>
            {subjectError && (
              <div className="form-field-error">Subject should be at least 3 characters if provided.</div>
            )}
          </div>

          <div className="form-group">
            <label htmlFor="ticket_type_id">Ticket Type <span className="required">*</span></label>
            <select
              id="ticket_type_id"
              name="ticket_type_id"
              value={formData.ticket_type_id}
              onChange={handleChange}
              required
              aria-required="true"
            >
              <option value="">Select type</option>
              {ticketTypes.map((t) => (
                <option key={t.type_id} value={t.type_id}>
                  {t.type_name}
                </option>
              ))}
            </select>
          </div>

          <div className="form-group form-group-email">
            <label htmlFor="recipient_email">Receiver Email</label>
            <input
              id="recipient_email"
              name="recipient_email"
              type="email"
              value={formData.recipient_email}
              onChange={handleChange}
              placeholder="eframeinterns@gmail.com"
              aria-describedby="recipient-hint"
            />
            <div id="recipient-hint" className="form-hint">Email address that will receive the ticket notification.</div>
          </div>
        </div>

        <div className="form-group">
          <label htmlFor="description">Issue Description <span className="required">*</span></label>
          <textarea
            id="description"
            name="description"
            value={formData.description}
            onChange={handleChange}
            onBlur={handleBlur}
            placeholder="Describe the issue in detail. Include steps to reproduce, error messages, and what you expected. This will be included in the email sent to the receiver."
            rows={6}
            minLength={DESCRIPTION_MIN}
            maxLength={DESCRIPTION_MAX}
            required
            aria-required="true"
            aria-describedby="description-hint description-count"
            aria-invalid={descriptionError}
            className={descriptionError ? 'input-error' : descriptionWarn ? 'input-warn' : ''}
          />
          <div id="description-hint" className="form-hint">
            Minimum {DESCRIPTION_MIN} characters. More detail usually leads to faster resolution.
          </div>
          <div id="description-count" className="form-char-count" aria-live="polite">
            {formData.description.length}/{DESCRIPTION_MAX}
            {formData.description.length > 0 && formData.description.length < DESCRIPTION_MIN && (
              <span className="form-char-count-min"> (min {DESCRIPTION_MIN})</span>
            )}
          </div>
          {descriptionError && (
            <div className="form-field-error">Please provide at least {DESCRIPTION_MIN} characters.</div>
          )}
          {descriptionWarn && !descriptionError && (
            <div className="form-field-warn">Adding more detail can help us resolve your issue faster.</div>
          )}
        </div>

        <div className="form-group form-group-attachments">
          <label htmlFor="attachments" className="raise-ticket-attachments-label">
            Attach media (optional)
          </label>
          <p id="attachments-hint" className="form-hint raise-ticket-attachments-hint">
            Add screenshots, videos, or PDFs to include with the email. Max {MAX_ATTACHMENTS} files, {MAX_FILE_SIZE_MB} MB each.
          </p>
          <input
            id="attachments"
            name="attachments"
            type="file"
            multiple
            accept={ACCEPT_MEDIA}
            onChange={handleFileChange}
            className="raise-ticket-file-input"
            aria-describedby="attachments-hint"
          />
          <div className="raise-ticket-file-drop-zone" onClick={() => document.getElementById('attachments')?.click()}>
            <span className="raise-ticket-file-drop-icon" aria-hidden="true">
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" />
              </svg>
            </span>
            <span className="raise-ticket-file-drop-text">Click to add screenshots or video</span>
          </div>
          {attachmentError && (
            <div className="form-field-error raise-ticket-attachment-error" role="alert">{attachmentError}</div>
          )}
          {attachments.length > 0 && (
            <ul className="raise-ticket-attachment-list" aria-label="Attached files">
              {attachments.map((file, index) => (
                <li key={`${file.name}-${file.size}-${index}`} className="raise-ticket-attachment-item">
                  <span className="raise-ticket-attachment-name" title={file.name}>{file.name}</span>
                  <span className="raise-ticket-attachment-size">{formatFileSize(file.size)}</span>
                  <button
                    type="button"
                    className="raise-ticket-attachment-remove"
                    onClick={() => removeAttachment(index)}
                    aria-label={`Remove ${file.name}`}
                  >
                    ×
                  </button>
                </li>
              ))}
            </ul>
          )}
        </div>

        <div className="form-actions">
          <button
            type="submit"
            className="btn-submit"
            disabled={loading || !canSubmit}
            aria-busy={loading}
          >
            {loading ? (
              <>
                <span className="btn-spinner" aria-hidden="true" />
                Raising ticket...
              </>
            ) : (
              'Raise Ticket'
            )}
          </button>
          <button
            type="button"
            className="btn-secondary"
            onClick={() => setShowClearConfirm(true)}
            disabled={loading}
          >
            Clear form
          </button>
          <button
            type="button"
            className="btn-ghost"
            onClick={() => navigate('/tickets')}
            disabled={loading}
          >
            Cancel
          </button>
        </div>
      </form>

      {showClearConfirm && (
        <div className="raise-ticket-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="clear-modal-title">
          <div className="raise-ticket-modal">
            <h2 id="clear-modal-title">Clear form?</h2>
            <p>All entered data and attachments will be lost. This cannot be undone.</p>
            <div className="raise-ticket-modal-actions">
              <button type="button" className="btn-submit" onClick={handleClearForm}>Clear</button>
              <button type="button" className="btn-secondary" onClick={() => setShowClearConfirm(false)}>Keep editing</button>
            </div>
          </div>
        </div>
      )}

      <SuccessPopup
        show={showPopup}
        message={popupMessage}
        onClose={handlePopupClose}
      />
      <ErrorPopup
        show={!!error}
        message={error || ''}
        onClose={() => setError(null)}
      />
    </div>
  );
};

export default RaiseTicket;
