'use client';
import { useEffect, useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import { Form, Switch, Row, Col, Divider, Typography, Spin } from 'antd';
import { useForm, Controller } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { FormDrawer } from '@/components/ui/drawers/FormDrawer';
import { AppSelect } from '@/components/ui/selects/AppSelect';
import { AppInputNumber } from '@/components/ui/inputs/AppInputNumber';
import dayjs from 'dayjs';
import { employersApi, jobsApi } from '@/services/api';
import { handleApiError } from '@/services/helpers/toast.helpers';
import type { Job, JobDynamicFieldValue } from '@/types/common.types';
import type { UploadResult } from '@/components/ui/uploader';
import { JobDynamicFormSections } from './JobDynamicFormSections';
import { extractDynamicFieldValue } from '@/modules/dynamic-fields/dynamic-field-value.util';
import { useDynamicFields } from '@/modules/dynamic-fields/useDynamicFields';
import { jobFormSchema, type JobFormData } from './job.schema';
import type { DynamicField } from '@/types/common.types';

const IMAGE_KEY_PATTERN = /\.(jpe?g|png|webp|gif|avif)$/i;

function dynamicFieldValueToFormValue(f: JobDynamicFieldValue): unknown {
  if (!f.value) return undefined;
  if (f.type === 'file') {
    const key = String(f.value);
    const fileName = key.split('/').pop() ?? key;
    const upload: UploadResult = {
      key, url: f.file_url ?? '', fileName, originalName: fileName,
      fileSize: 0, mimeType: '', isImage: IMAGE_KEY_PATTERN.test(key),
    };
    return upload;
  }
  if (f.type === 'date' || f.type === 'datetime') {
    return dayjs(f.value as string);
  }
  return f.value;
}

// `images` holds stable S3 keys; `image_urls` holds freshly signed display URLs
// generated by the API on every fetch — zip them back together by index for the uploader.
function jobImagesToUploadResults(job: Job): UploadResult[] {
  return (job.images ?? []).map((key, i) => {
    const fileName = key.split('/').pop() ?? key;
    return {
      key,
      url: job.image_urls?.[i] ?? '',
      fileName,
      originalName: fileName,
      fileSize: 0,
      mimeType: 'image/*',
      isImage: true,
    };
  });
}

const { Text } = Typography;

const JOB_TYPE_OPTIONS = [
  { value: 'one_day', label: 'One Day' },
  { value: 'short_term', label: 'Short Term' },
  { value: 'long_term', label: 'Long Term' },
  { value: 'contract', label: 'Contract' },
  { value: 'permanent', label: 'Permanent' },
];

const STATUS_OPTIONS = [
  { value: 'active', label: 'Active' },
  { value: 'inactive', label: 'Inactive' },
  { value: 'expired', label: 'Expired' },
];

interface EmployerOption { value: string; label: string; status: string; }

interface JobEditModalProps {
  open: boolean;
  job: Job | null;
  onClose: () => void;
  onSubmit: (id: string, data: Record<string, unknown>) => void;
  loading?: boolean;
}

const EMPTY_VALUES: JobFormData = {
  employer_id: '', title: '', category_id: '', subcategory_id: '',
  business_data: {}, dynamic_field_values: {},
  start_date_time: undefined as never, end_date_time: undefined as never,
  location_address: '',
  latitude: undefined as never, longitude: undefined as never,
  image_uploads: [],
  required_application_fields: { resume: false, education: false, experience: false, skills: false },
  type: 'long_term', openings: 1, status: 'active', is_featured: false, is_urgent: false,
};

/** Validates the current subcategory's dynamic fields against `values` and injects errors via
 * `setError` — their shape is only known at runtime (see DynamicFieldsRenderer), so this can't
 * live in the static zod schema. */
function validateDynamicFields(
  dynamicFields: DynamicField[],
  values: Record<string, unknown>,
  setError: (name: `dynamic_field_values.${string}`, error: { type: string; message: string }) => void,
): boolean {
  let ok = true;
  for (const f of dynamicFields) {
    const value = values[f.id];
    const isEmpty = value === undefined || value === null || value === '' || (Array.isArray(value) && value.length === 0);
    if (f.is_required && isEmpty) {
      setError(`dynamic_field_values.${f.id}`, { type: 'required', message: `${f.field_label} is required` });
      ok = false;
      continue;
    }
    if (isEmpty) continue;
    if (f.validation_rules?.min_length && typeof value === 'string' && value.length < f.validation_rules.min_length) {
      setError(`dynamic_field_values.${f.id}`, { type: 'minLength', message: `${f.field_label} must be at least ${f.validation_rules.min_length} characters` });
      ok = false;
    }
    if (f.field_type === 'email' && typeof value === 'string' && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
      setError(`dynamic_field_values.${f.id}`, { type: 'email', message: `${f.field_label} must be a valid email address` });
      ok = false;
    }
    if (f.field_type === 'url' && typeof value === 'string' && !/^https?:\/\/.+/.test(value)) {
      setError(`dynamic_field_values.${f.id}`, { type: 'url', message: `${f.field_label} must be a valid URL` });
      ok = false;
    }
  }
  return ok;
}

export function JobEditModal({ open, job, onClose, onSubmit, loading }: JobEditModalProps) {
  const [categoryId, setCategoryId] = useState<string | null>(null);
  const [categoryName, setCategoryName] = useState<string | null>(null);
  const [subcategoryId, setSubcategoryId] = useState<string | null>(null);
  const [subcategoryName, setSubcategoryName] = useState<string | null>(null);
  const [employers, setEmployers] = useState<EmployerOption[]>([]);
  const [employersLoading, setEmployersLoading] = useState(false);

  const { control, handleSubmit, reset, setValue, getValues, setError, watch } = useForm<JobFormData>({
    resolver: zodResolver(jobFormSchema),
    defaultValues: EMPTY_VALUES,
  });

  const watchedSubcategoryId = watch('subcategory_id');
  const { fields: dynamicFields } = useDynamicFields(watchedSubcategoryId || null);

  // The jobs table row passed in as `job` doesn't include `dynamic_fields` (only the
  // single-job detail endpoint does) — fetch it fresh so dynamic field values actually prefill.
  const jobId = job?.id;
  const { data: jobDetail } = useQuery({
    queryKey: ['job-detail', jobId],
    queryFn: () => jobsApi.getById(jobId as string),
    enabled: open && !!jobId,
  });

  useEffect(() => {
    if (!open) return;
    setEmployersLoading(true);
    employersApi.getAll({ limit: 500 })
      .then((res) => {
        setEmployers((prev) => {
          const fetched = res.data.map((e) => ({ value: e.id, label: e.company_name, status: e.status }));
          const byValue = new Map(prev.map((o) => [o.value, o]));
          for (const o of fetched) byValue.set(o.value, o);
          return Array.from(byValue.values());
        });
      })
      .catch((err) => handleApiError(err, 'Failed to load employers'))
      .finally(() => setEmployersLoading(false));
  }, [open]);

  useEffect(() => {
    if (!job || !open) return;

    setCategoryId(job.category_id);
    setCategoryName(job.category_name);
    setSubcategoryId(job.subcategory_id);
    setSubcategoryName(job.subcategory_name);
    // Seed immediately with the employer already on the job so the Select shows the
    // right company even before (or if) the full employers list finishes loading.
    const currentEmployerName = job.company_name ?? job.employer_name;
    if (currentEmployerName) {
      setEmployers((prev) => (prev.some((o) => o.value === job.employer_id)
        ? prev
        : [...prev, { value: job.employer_id, label: currentEmployerName, status: 'active' }]));
    }

    reset({
      employer_id: job.employer_id,
      title: job.title,
      category_id: job.category_id ?? '',
      subcategory_id: job.subcategory_id ?? '',
      business_data: job.business_data ?? {},
      dynamic_field_values: Object.fromEntries((job.dynamic_fields ?? []).map((f) => [f.id, dynamicFieldValueToFormValue(f)])),
      start_date_time: job.start_date_time ? dayjs(job.start_date_time) : (undefined as never),
      end_date_time: job.end_date_time ? dayjs(job.end_date_time) : (undefined as never),
      latitude: (job.latitude ?? undefined) as never,
      longitude: (job.longitude ?? undefined) as never,
      location_address: job.location_address ?? '',
      image_uploads: jobImagesToUploadResults(job),
      required_application_fields: {
        resume: job.required_application_fields?.resume ?? false,
        education: job.required_application_fields?.education ?? false,
        experience: job.required_application_fields?.experience ?? false,
        skills: job.required_application_fields?.skills ?? false,
      },
      type: job.type,
      status: job.status,
      openings: job.openings,
      is_featured: job.is_featured,
      is_urgent: job.is_urgent,
    });
  }, [job, open, reset]);

  // The jobs table row (`job`) doesn't carry `dynamic_fields` — only the single-job detail
  // fetch above does. Patch just that one field in once it resolves, without touching anything
  // else the effect above already prefilled correctly.
  useEffect(() => {
    if (!jobDetail || !open) return;
    for (const f of jobDetail.dynamic_fields ?? []) {
      setValue(`dynamic_field_values.${f.id}` as never, dynamicFieldValueToFormValue(f) as never);
    }
  }, [jobDetail, open, setValue]);

  useEffect(() => {
    if (!open) reset(EMPTY_VALUES);
  }, [open, reset]);

  const handleClose = () => {
    onClose();
    reset(EMPTY_VALUES);
  };

  const handleFormSubmit = (values: JobFormData) => {
    if (!job) return;
    if (!validateDynamicFields(dynamicFields, values.dynamic_field_values, setError)) return;

    const businessData = values.business_data ?? {};
    const fmt = (v: unknown): string | undefined => {
      const d = v as { toISOString?: () => string } | undefined;
      return d && typeof d.toISOString === 'function' ? d.toISOString() : undefined;
    };

    const uploads = values.image_uploads ?? [];
    const dynamicFieldValues = values.dynamic_field_values ?? {};
    const { image_uploads: _imageUploads, dynamic_field_values: _dynamicFieldValues, ...rest } = values;

    const payload: Record<string, unknown> = {
      ...rest,
      business_data: businessData,
      // Only submit values for fields still active on this subcategory — a value can linger in
      // form state (prefilled from the job's saved history) for a field that's since been
      // deactivated/removed, and the backend rejects the whole update if it sees an unknown
      // dynamic_field_id.
      dynamic_field_values: Object.entries(dynamicFieldValues)
        .map(([dynamic_field_id, value]) => ({
          dynamic_field_id,
          field: dynamicFields.find((f) => f.id === dynamic_field_id),
          value,
        }))
        .filter((f): f is typeof f & { field: DynamicField } => !!f.field)
        .map(({ dynamic_field_id, field, value }) => ({
          dynamic_field_id,
          value: extractDynamicFieldValue(value, field.field_type),
        }))
        .filter(({ value }) => value !== undefined && value !== null && value !== ''),
      salary: businessData['salary'] != null ? String(businessData['salary']) : undefined,
      start_date_time: fmt(values.start_date_time),
      end_date_time: fmt(values.end_date_time),
      images: (uploads as UploadResult[]).map((u) => u.key),
    };
    onSubmit(job.id, payload);
  };

  return (
    <FormDrawer
      title="Edit Job"
      subtitle={job?.title}
      open={open}
      onClose={handleClose}
      onSubmit={handleSubmit(handleFormSubmit)}
      loading={loading}
      submitLabel="Save Changes"
      size="large"
    >
      <Form layout="vertical" component="div">
        <Divider orientation="left" orientationMargin={0}>
          <Text style={{ fontSize: 12, color: '#64748b' }}>Employer</Text>
        </Divider>

        <AppSelect<JobFormData>
          name="employer_id"
          control={control}
          label="Employer"
          required
          showSearch
          placeholder={employersLoading && employers.length === 0 ? 'Loading employers...' : 'Search by company name...'}
          notFoundContent={employersLoading ? <Spin size="small" /> : 'No employers found'}
          filterOption={(input, opt) => String(opt?.label ?? '').toLowerCase().includes(input.toLowerCase())}
          optionRender={(opt) => {
            const item = employers.find((e) => e.value === opt.value);
            return (
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                <span style={{ fontSize: 12 }}>{opt.label}</span>
                {item && (
                  <span style={{
                    fontSize: 10, padding: '1px 6px', borderRadius: 4,
                    background: item.status === 'active' ? '#dcfce7' : '#fef3c7',
                    color: item.status === 'active' ? '#16a34a' : '#92400e',
                  }}>
                    {item.status}
                  </span>
                )}
              </div>
            );
          }}
          options={employers.map((e) => ({ value: e.value, label: e.label }))}
        />

        <JobDynamicFormSections
          control={control}
          setValue={setValue}
          getValues={getValues}
          initialCategoryId={categoryId}
          initialCategoryName={categoryName}
          initialSubcategoryId={subcategoryId}
          initialSubcategoryName={subcategoryName}
        />

        {/* ── Admin Settings ──────────────────────────────────────── */}
        <Divider orientation="left" orientationMargin={0}>
          <Text style={{ fontSize: 12, color: '#64748b' }}>Admin Settings</Text>
        </Divider>

        <Row gutter={12}>
          <Col span={8}>
            <AppSelect<JobFormData> name="type" control={control} label="Job Type" options={JOB_TYPE_OPTIONS} />
          </Col>
          <Col span={8}>
            <AppInputNumber<JobFormData> name="openings" control={control} label="Openings" min={1} />
          </Col>
          <Col span={8}>
            <AppSelect<JobFormData> name="status" control={control} label="Status" options={STATUS_OPTIONS} />
          </Col>
        </Row>

        <Row gutter={12}>
          <Col span={8}>
            <Controller
              name="is_featured"
              control={control}
              render={({ field }) => (
                <Form.Item label="Featured Job">
                  <Switch checkedChildren="Featured" unCheckedChildren="Normal" checked={field.value} onChange={field.onChange} />
                </Form.Item>
              )}
            />
          </Col>
          <Col span={8}>
            <Controller
              name="is_urgent"
              control={control}
              render={({ field }) => (
                <Form.Item label="Urgent Hiring">
                  <Switch checkedChildren="Urgent" unCheckedChildren="Normal" checked={field.value} onChange={field.onChange} />
                </Form.Item>
              )}
            />
          </Col>
        </Row>
      </Form>
    </FormDrawer>
  );
}
