import React, { useEffect, useMemo, useState } from 'react';
import { ProfileAnswerInput, ProfileQuestionForUser } from '../services/membershipService';
import {
  answerToComparable,
  canEditProfileQuestion,
  isProfileQuestionVisible,
  ProfileQuestionAnswerValue
} from '../utils/profileQuestionLogic';

interface ProfileQuestionsFormProps {
  title: string;
  description?: string;
  questions: ProfileQuestionForUser[];
  onSave: (answers: ProfileAnswerInput[]) => Promise<void>;
  saveLabel?: string;
  allowAdminManagedEdit?: boolean;
  surface?: 'member' | 'admin';
}

const formatAnswerForDisplay = (question: ProfileQuestionForUser, value: ProfileQuestionAnswerValue): string => {
  if (value === null || value === undefined || value === '') return 'Not set';
  if (question.input_type === 'boolean') return value === true || value === 'true' ? 'Yes' : 'No';
  if (question.input_type === 'select') {
    const matchingOption = question.options.find((option) => option.value === String(value));
    return matchingOption?.label || String(value);
  }
  return String(value);
};

const ProfileQuestionsForm: React.FC<ProfileQuestionsFormProps> = ({
  title,
  description,
  questions,
  onSave,
  saveLabel = 'Save Answers',
  allowAdminManagedEdit = false,
  surface = 'admin'
}) => {
  const initialAnswers = useMemo(() => {
    const values: Record<number, ProfileQuestionAnswerValue> = {};
    questions.forEach((question) => {
      values[question.id] = question.answer ?? null;
    });
    return values;
  }, [questions]);

  const [answers, setAnswers] = useState<Record<number, ProfileQuestionAnswerValue>>(initialAnswers);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [successMessage, setSuccessMessage] = useState<string | null>(null);
  const [search, setSearch] = useState('');
  const [page, setPage] = useState(1);
  const pageSize = 10;

  useEffect(() => {
    setAnswers(initialAnswers);
    setSuccessMessage(null);
    setError(null);
  }, [initialAnswers]);

  const visibleQuestions = useMemo(() => {
    const byId = new Map<number, ProfileQuestionForUser>();
    questions.forEach((question) => byId.set(question.id, question));
    return questions.filter((question) => isProfileQuestionVisible(question, byId, answers));
  }, [questions, answers]);

  const filteredQuestions = useMemo(() => {
    const searchTerm = search.trim().toLowerCase();
    return visibleQuestions.filter((question) => {
      if (!searchTerm) return true;
      return (
        question.label.toLowerCase().includes(searchTerm) ||
        question.key.toLowerCase().includes(searchTerm) ||
        (question.help_text || '').toLowerCase().includes(searchTerm)
      );
    });
  }, [visibleQuestions, search]);

  const totalPages = Math.max(1, Math.ceil(filteredQuestions.length / pageSize));

  const paginatedQuestions = useMemo(() => {
    const safePage = Math.min(page, totalPages);
    const start = (safePage - 1) * pageSize;
    return filteredQuestions.slice(start, start + pageSize);
  }, [filteredQuestions, page, totalPages]);

  const setAnswerValue = (questionId: number, value: ProfileQuestionAnswerValue) => {
    setAnswers((prev) => ({ ...prev, [questionId]: value }));
    setSuccessMessage(null);
    setError(null);
  };

  useEffect(() => {
    setPage(1);
  }, [search]);

  const handleSave = async () => {
    setSaving(true);
    setError(null);
    setSuccessMessage(null);

    try {
      const visibleQuestionIds = new Set(visibleQuestions.map((question) => question.id));
      const changedAnswers: ProfileAnswerInput[] = questions
        .filter((question) => canEditProfileQuestion(question, allowAdminManagedEdit) && visibleQuestionIds.has(question.id))
        .filter((question) => answerToComparable(answers[question.id] ?? null) !== answerToComparable(initialAnswers[question.id] ?? null))
        .map((question) => ({
          question_id: question.id,
          value: answers[question.id] ?? null
        }));

      await onSave(changedAnswers);
      setSuccessMessage(changedAnswers.length > 0 ? 'Saved successfully.' : 'No changes to save.');
    } catch (err: any) {
      setError(err.response?.data?.detail || err.message || 'Failed to save answers.');
    } finally {
      setSaving(false);
    }
  };

  const renderField = (question: ProfileQuestionForUser) => {
    const value = answers[question.id] ?? null;
    const disabled = !canEditProfileQuestion(question, allowAdminManagedEdit) || saving;

    if (disabled && !saving) {
      return <div className="profile-question-readonly">{formatAnswerForDisplay(question, value)}</div>;
    }

    if (question.input_type === 'boolean') {
      return (
        <select
          value={value === null ? '' : String(value)}
          onChange={(event) => setAnswerValue(question.id, event.target.value === '' ? null : event.target.value === 'true')}
          disabled={disabled}
          className="profile-question-input"
        >
          <option value="">Prefer not to say</option>
          <option value="true">Yes</option>
          <option value="false">No</option>
        </select>
      );
    }

    if (question.input_type === 'select') {
      return (
        <select
          value={value === null ? '' : String(value)}
          onChange={(event) => setAnswerValue(question.id, event.target.value || null)}
          disabled={disabled}
          className="profile-question-input"
        >
          <option value="">Select an option</option>
          {question.options.map((option) => (
            <option key={option.value} value={option.value}>{option.label}</option>
          ))}
        </select>
      );
    }

    if (question.input_type === 'date') {
      return (
        <input
          type="date"
          value={value === null ? '' : String(value)}
          onChange={(event) => setAnswerValue(question.id, event.target.value || null)}
          disabled={disabled}
          className="profile-question-input"
        />
      );
    }

    if (question.input_type === 'number') {
      return (
        <input
          type="number"
          value={value === null ? '' : String(value)}
          onChange={(event) => setAnswerValue(question.id, event.target.value === '' ? null : Number(event.target.value))}
          disabled={disabled}
          placeholder={question.placeholder || ''}
          className="profile-question-input"
        />
      );
    }

    return (
      <input
        type="text"
        value={value === null ? '' : String(value)}
        onChange={(event) => setAnswerValue(question.id, event.target.value || null)}
        disabled={disabled}
        placeholder={question.placeholder || ''}
        className="profile-question-input"
      />
    );
  };

  return (
    <div className={`card profile-questions-form ${surface === 'member' ? 'member-surface' : 'admin-surface'}`}>
      <h3 className="profile-questions-title">{title}</h3>
      {description && <p className="profile-questions-description">{description}</p>}

      <div className="profile-questions-search">
        <input
          type="text"
          placeholder="Search questions..."
          value={search}
          onChange={(event) => setSearch(event.target.value)}
          className="profile-question-input"
        />
      </div>

      {error && <div className="alert alert-error">{error}</div>}
      {successMessage && <div className="alert alert-success">{successMessage}</div>}

      {filteredQuestions.length === 0 ? (
        <p className="profile-questions-empty">No questions available.</p>
      ) : (
        <div className="profile-questions-list">
          {paginatedQuestions.map((question) => (
            <div
              key={question.id}
              className={`profile-question-row ${surface === 'member' ? 'profile-question-row-member' : 'profile-question-row-admin'}`}
            >
              <div className="profile-question-meta">
                <label className="profile-question-label">
                  {question.label}
                  {question.is_required && <span className="profile-question-required"> *</span>}
                  {question.admin_only_edit && <span className="admin-inline-badge">Admin Managed</span>}
                </label>
                {question.help_text && (
                  <p className="profile-question-help">{question.help_text}</p>
                )}
              </div>
              <div className="profile-question-answer">{renderField(question)}</div>
              {!canEditProfileQuestion(question, allowAdminManagedEdit) && (
                <p className="profile-question-lock-note">
                  This field can only be changed by an admin.
                </p>
              )}
            </div>
          ))}
        </div>
      )}

      {filteredQuestions.length > pageSize && (
        <div className="profile-questions-pagination">
          <span className="profile-questions-page-copy">
            Page {Math.min(page, totalPages)} of {totalPages} ({filteredQuestions.length} questions)
          </span>
          <div className="profile-questions-pager-buttons">
            <button className="btn btn-secondary profile-questions-pager-button" disabled={page <= 1} onClick={() => setPage((prev) => Math.max(1, prev - 1))}>
              Previous
            </button>
            <button className="btn btn-secondary profile-questions-pager-button" disabled={page >= totalPages} onClick={() => setPage((prev) => Math.min(totalPages, prev + 1))}>
              Next
            </button>
          </div>
        </div>
      )}

      <div className="profile-questions-actions">
        <button className="btn btn-primary" onClick={handleSave} disabled={saving}>
          {saving ? 'Saving...' : saveLabel}
        </button>
      </div>
    </div>
  );
};

export default ProfileQuestionsForm;
