import { useEffect, useState, useCallback } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import {
  Card, Form, Input, Switch, Button, Space, Typography, Row, Col, DatePicker,
  InputNumber, Select, Spin, App, List, Popconfirm, Grid, Tag,
} from 'antd';
import {
  ArrowLeftOutlined, SaveOutlined, PlusOutlined, DeleteOutlined,
  ArrowUpOutlined, ArrowDownOutlined, VideoCameraOutlined, MailOutlined,
  FileTextOutlined, CalendarOutlined, EnvironmentOutlined, TeamOutlined,
  LinkOutlined, CheckSquareOutlined,
} from '@ant-design/icons';
import dayjs from 'dayjs';
import { api } from '@/lib/api';
import { mediaApi } from '@/lib/media-api';

type ActionStepKind =
  | 'WATCH_VIDEO'
  | 'SUBMIT_INFLUENCE'
  | 'SIGN_PETITION'
  | 'RSVP_EVENT'
  | 'SIGNUP_SHIFT'
  | 'JOIN_CHALLENGE'
  | 'VISIT_LINK'
  | 'CUSTOM';

interface ActionStep {
  id: string;
  order: number;
  kind: ActionStepKind;
  label: string;
  description: string | null;
  targetId: string | null;
  targetUrl: string | null;
  autoComplete: boolean;
}

interface ActionCampaign {
  id: string;
  slug: string;
  title: string;
  description: string | null;
  rewardText: string | null;
  isActive: boolean;
  startsAt: string | null;
  endsAt: string | null;
  minStepsForReward: number | null;
  steps: ActionStep[];
}

const KIND_OPTIONS: { value: ActionStepKind; label: string; icon: React.ReactNode }[] = [
  { value: 'WATCH_VIDEO', label: 'Watch video', icon: <VideoCameraOutlined /> },
  { value: 'SUBMIT_INFLUENCE', label: 'Submit advocacy campaign', icon: <MailOutlined /> },
  { value: 'SIGN_PETITION', label: 'Sign petition', icon: <FileTextOutlined /> },
  { value: 'RSVP_EVENT', label: 'RSVP to event', icon: <CalendarOutlined /> },
  { value: 'SIGNUP_SHIFT', label: 'Sign up for shift', icon: <EnvironmentOutlined /> },
  { value: 'JOIN_CHALLENGE', label: 'Join challenge', icon: <TeamOutlined /> },
  { value: 'VISIT_LINK', label: 'Visit link', icon: <LinkOutlined /> },
  { value: 'CUSTOM', label: 'Custom (self-report)', icon: <CheckSquareOutlined /> },
];

interface PickerOption {
  value: string;
  label: string;
}

function slugify(str: string): string {
  return str
    .toLowerCase()
    .trim()
    .replace(/[^\w\s-]/g, '')
    .replace(/[\s_-]+/g, '-')
    .replace(/^-+|-+$/g, '');
}

export default function ActionCampaignEditorPage() {
  const { id } = useParams<{ id: string }>();
  const navigate = useNavigate();
  const { message } = App.useApp();
  const screens = Grid.useBreakpoint();
  const isMobile = !screens.md;
  const isNew = !id || id === 'new';

  const [form] = Form.useForm();
  const [loading, setLoading] = useState(!isNew);
  const [saving, setSaving] = useState(false);
  const [steps, setSteps] = useState<ActionStep[]>([]);
  const [campaignId, setCampaignId] = useState<string | null>(isNew ? null : id || null);
  const [slugTouched, setSlugTouched] = useState(!isNew);

  const [videoOpts, setVideoOpts] = useState<PickerOption[]>([]);
  const [influenceOpts, setInfluenceOpts] = useState<PickerOption[]>([]);
  const [petitionOpts, setPetitionOpts] = useState<PickerOption[]>([]);
  const [eventOpts, setEventOpts] = useState<PickerOption[]>([]);
  const [shiftOpts, setShiftOpts] = useState<PickerOption[]>([]);
  const [challengeOpts, setChallengeOpts] = useState<PickerOption[]>([]);

  const loadCampaign = useCallback(async () => {
    if (isNew) return;
    setLoading(true);
    try {
      const { data } = await api.get<ActionCampaign>(`/admin/action-campaigns/${id}`);
      form.setFieldsValue({
        title: data.title,
        slug: data.slug,
        description: data.description,
        rewardText: data.rewardText,
        isActive: data.isActive,
        minStepsForReward: data.minStepsForReward,
        startsAt: data.startsAt ? dayjs(data.startsAt) : null,
        endsAt: data.endsAt ? dayjs(data.endsAt) : null,
      });
      setSteps([...data.steps].sort((a, b) => a.order - b.order));
      setCampaignId(data.id);
    } catch {
      message.error('Failed to load action campaign');
      navigate('/app/influence/action-campaigns');
    } finally {
      setLoading(false);
    }
  }, [id, isNew, form, message, navigate]);

  useEffect(() => {
    loadCampaign();
  }, [loadCampaign]);

  useEffect(() => {
    (async () => {
      try {
        const res = await mediaApi.get('/videos?limit=200');
        const videos = res.data?.videos || [];
        setVideoOpts(
          videos.map((v: { id: number | string; title: string }) => ({
            value: String(v.id),
            label: v.title,
          })),
        );
      } catch {
        /* non-critical */
      }
    })();

    (async () => {
      try {
        const { data } = await api.get('/influence/campaigns', { params: { limit: 200 } });
        const items = data?.campaigns || data?.items || [];
        setInfluenceOpts(
          items.map((c: { slug: string; title: string }) => ({
            value: c.slug,
            label: c.title,
          })),
        );
      } catch {
        try {
          const { data } = await api.get('/campaigns', { params: { limit: 200 } });
          const items = data?.campaigns || [];
          setInfluenceOpts(
            items.map((c: { slug: string; title: string }) => ({
              value: c.slug,
              label: c.title,
            })),
          );
        } catch {
          /* non-critical */
        }
      }
    })();

    (async () => {
      try {
        const { data } = await api.get('/petitions', { params: { limit: 200 } });
        const items = data?.petitions || [];
        setPetitionOpts(
          items.map((p: { slug: string; title: string }) => ({
            value: p.slug,
            label: p.title,
          })),
        );
      } catch {
        /* non-critical */
      }
    })();

    (async () => {
      try {
        const { data } = await api.get('/ticketed-events/admin', { params: { limit: 200 } });
        const items = data?.events || data?.items || [];
        setEventOpts(
          items.map((e: { slug: string; title: string }) => ({
            value: e.slug,
            label: e.title,
          })),
        );
      } catch {
        /* non-critical */
      }
    })();

    (async () => {
      try {
        const { data } = await api.get('/map/shifts', { params: { limit: 200 } });
        const items = data?.shifts || data?.items || [];
        setShiftOpts(
          items.map((s: { id: string; title: string; name?: string }) => ({
            value: s.id,
            label: s.title || s.name || s.id,
          })),
        );
      } catch {
        /* non-critical */
      }
    })();

    (async () => {
      try {
        const { data } = await api.get('/social/challenges', { params: { limit: 200 } });
        const items = data?.challenges || data?.items || [];
        setChallengeOpts(
          items.map((c: { id: string; title: string; name?: string }) => ({
            value: c.id,
            label: c.title || c.name || c.id,
          })),
        );
      } catch {
        /* non-critical */
      }
    })();
  }, []);

  const handleTitleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (!slugTouched && isNew) {
      form.setFieldValue('slug', slugify(e.target.value));
    }
  };

  const handleSave = async () => {
    try {
      const values = await form.validateFields();
      setSaving(true);
      const payload = {
        title: values.title,
        slug: values.slug,
        description: values.description || null,
        rewardText: values.rewardText || null,
        isActive: values.isActive ?? false,
        minStepsForReward: values.minStepsForReward ?? null,
        startsAt: values.startsAt ? values.startsAt.toISOString() : null,
        endsAt: values.endsAt ? values.endsAt.toISOString() : null,
      };
      if (isNew && !campaignId) {
        const { data } = await api.post<ActionCampaign>('/admin/action-campaigns', payload);
        message.success('Action campaign created');
        setCampaignId(data.id);
        navigate(`/app/influence/action-campaigns/${data.id}`, { replace: true });
      } else if (campaignId) {
        await api.put(`/admin/action-campaigns/${campaignId}`, payload);
        message.success('Action campaign saved');
      }
    } catch (err) {
      if ((err as { errorFields?: unknown }).errorFields) return;
      message.error('Failed to save campaign');
    } finally {
      setSaving(false);
    }
  };

  const handleAddStep = async () => {
    if (!campaignId) {
      message.warning('Save the campaign first before adding steps');
      return;
    }
    try {
      const { data } = await api.post<ActionStep>(
        `/admin/action-campaigns/${campaignId}/steps`,
        {
          kind: 'CUSTOM',
          label: 'New step',
          description: null,
          targetId: null,
          targetUrl: null,
        },
      );
      setSteps((prev) => [...prev, data]);
    } catch {
      message.error('Failed to add step');
    }
  };

  const handleUpdateStep = async (step: ActionStep, patch: Partial<ActionStep>) => {
    if (!campaignId) return;
    const next = { ...step, ...patch };
    setSteps((prev) => prev.map((s) => (s.id === step.id ? next : s)));
    try {
      await api.put(`/admin/action-campaigns/${campaignId}/steps/${step.id}`, {
        kind: next.kind,
        label: next.label,
        description: next.description,
        targetId: next.targetId,
        targetUrl: next.targetUrl,
      });
    } catch {
      message.error('Failed to update step');
      setSteps((prev) => prev.map((s) => (s.id === step.id ? step : s)));
    }
  };

  const handleDeleteStep = async (step: ActionStep) => {
    if (!campaignId) return;
    try {
      await api.delete(`/admin/action-campaigns/${campaignId}/steps/${step.id}`);
      setSteps((prev) => prev.filter((s) => s.id !== step.id));
    } catch {
      message.error('Failed to delete step');
    }
  };

  const handleReorder = async (from: number, to: number) => {
    if (!campaignId) return;
    if (to < 0 || to >= steps.length) return;
    if (from < 0 || from >= steps.length) return;
    const next = [...steps];
    const moved = next[from];
    if (!moved) return;
    next.splice(from, 1);
    next.splice(to, 0, moved);
    setSteps(next);
    try {
      await api.post(`/admin/action-campaigns/${campaignId}/steps/reorder`, {
        stepIds: next.map((s) => s.id),
      });
    } catch {
      message.error('Failed to reorder steps');
      setSteps(steps);
    }
  };

  if (loading) {
    return (
      <div style={{ textAlign: 'center', padding: 48 }}>
        <Spin size="large" />
      </div>
    );
  }

  return (
    <div style={{ padding: isMobile ? 16 : 24 }}>
      <div style={{ marginBottom: 16, display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>
        <Button icon={<ArrowLeftOutlined />} onClick={() => navigate('/app/influence/action-campaigns')}>
          Back
        </Button>
        <Typography.Title level={4} style={{ margin: 0 }}>
          {isNew ? 'New Action Campaign' : 'Edit Action Campaign'}
        </Typography.Title>
        <div style={{ marginLeft: 'auto' }}>
          <Button type="primary" icon={<SaveOutlined />} loading={saving} onClick={handleSave}>
            Save
          </Button>
        </div>
      </div>

      <Row gutter={[16, 16]}>
        <Col xs={24} lg={12}>
          <Card title="Details">
            <Form form={form} layout="vertical" initialValues={{ isActive: false }}>
              <Form.Item
                name="title"
                label="Title"
                rules={[{ required: true, message: 'Title is required' }]}
              >
                <Input placeholder="Complete 3 actions to enter the draw" onChange={handleTitleChange} />
              </Form.Item>
              <Form.Item
                name="slug"
                label="Slug"
                rules={[
                  { required: true, message: 'Slug is required' },
                  { pattern: /^[a-z0-9-]+$/, message: 'Lowercase letters, numbers, and hyphens only' },
                ]}
              >
                <Input placeholder="complete-3-actions" onChange={() => setSlugTouched(true)} />
              </Form.Item>
              <Form.Item name="description" label="Description">
                <Input.TextArea rows={3} placeholder="Describe what volunteers will do and why" />
              </Form.Item>
              <Form.Item name="rewardText" label="Reward text">
                <Input placeholder="Entry into our $500 gift card draw" />
              </Form.Item>
              <Row gutter={16}>
                <Col xs={24} sm={12}>
                  <Form.Item name="startsAt" label="Starts at">
                    <DatePicker showTime style={{ width: '100%' }} />
                  </Form.Item>
                </Col>
                <Col xs={24} sm={12}>
                  <Form.Item name="endsAt" label="Ends at">
                    <DatePicker showTime style={{ width: '100%' }} />
                  </Form.Item>
                </Col>
              </Row>
              <Form.Item
                name="minStepsForReward"
                label="Minimum steps for reward"
                extra="Leave blank to require all steps"
              >
                <InputNumber min={1} style={{ width: '100%' }} />
              </Form.Item>
              <Form.Item name="isActive" label="Active" valuePropName="checked">
                <Switch />
              </Form.Item>
            </Form>
          </Card>
        </Col>

        <Col xs={24} lg={12}>
          <Card
            title="Steps"
            extra={
              <Button icon={<PlusOutlined />} onClick={handleAddStep} disabled={!campaignId}>
                Add step
              </Button>
            }
          >
            {!campaignId && (
              <Typography.Paragraph type="secondary">
                Save the campaign first to start adding steps.
              </Typography.Paragraph>
            )}
            {campaignId && steps.length === 0 && (
              <Typography.Paragraph type="secondary">
                No steps yet. Click "Add step" to add the first one.
              </Typography.Paragraph>
            )}
            <List
              dataSource={steps}
              rowKey="id"
              renderItem={(step, idx) => (
                <List.Item style={{ display: 'block', padding: '12px 0' }}>
                  <StepEditor
                    step={step}
                    index={idx}
                    total={steps.length}
                    videoOpts={videoOpts}
                    influenceOpts={influenceOpts}
                    petitionOpts={petitionOpts}
                    eventOpts={eventOpts}
                    shiftOpts={shiftOpts}
                    challengeOpts={challengeOpts}
                    onChange={(patch) => handleUpdateStep(step, patch)}
                    onDelete={() => handleDeleteStep(step)}
                    onMoveUp={() => handleReorder(idx, idx - 1)}
                    onMoveDown={() => handleReorder(idx, idx + 1)}
                  />
                </List.Item>
              )}
            />
          </Card>
        </Col>
      </Row>
    </div>
  );
}

interface StepEditorProps {
  step: ActionStep;
  index: number;
  total: number;
  videoOpts: PickerOption[];
  influenceOpts: PickerOption[];
  petitionOpts: PickerOption[];
  eventOpts: PickerOption[];
  shiftOpts: PickerOption[];
  challengeOpts: PickerOption[];
  onChange: (patch: Partial<ActionStep>) => void;
  onDelete: () => void;
  onMoveUp: () => void;
  onMoveDown: () => void;
}

function StepEditor({
  step, index, total, videoOpts, influenceOpts, petitionOpts,
  eventOpts, shiftOpts, challengeOpts, onChange, onDelete, onMoveUp, onMoveDown,
}: StepEditorProps) {
  const [localLabel, setLocalLabel] = useState(step.label);
  const [localDescription, setLocalDescription] = useState(step.description || '');
  const [localTargetUrl, setLocalTargetUrl] = useState(step.targetUrl || '');

  useEffect(() => {
    setLocalLabel(step.label);
    setLocalDescription(step.description || '');
    setLocalTargetUrl(step.targetUrl || '');
  }, [step.id, step.label, step.description, step.targetUrl]);

  const renderPicker = () => {
    switch (step.kind) {
      case 'WATCH_VIDEO':
        return (
          <Select
            showSearch
            placeholder="Select video"
            options={videoOpts}
            value={step.targetId || undefined}
            onChange={(val) => onChange({ targetId: val })}
            filterOption={(input, option) =>
              (option?.label as string)?.toLowerCase().includes(input.toLowerCase())
            }
            style={{ width: '100%' }}
          />
        );
      case 'SUBMIT_INFLUENCE':
        return (
          <Select
            showSearch
            placeholder="Select advocacy campaign"
            options={influenceOpts}
            value={step.targetId || undefined}
            onChange={(val) => onChange({ targetId: val })}
            filterOption={(input, option) =>
              (option?.label as string)?.toLowerCase().includes(input.toLowerCase())
            }
            style={{ width: '100%' }}
          />
        );
      case 'SIGN_PETITION':
        return (
          <Select
            showSearch
            placeholder="Select petition"
            options={petitionOpts}
            value={step.targetId || undefined}
            onChange={(val) => onChange({ targetId: val })}
            filterOption={(input, option) =>
              (option?.label as string)?.toLowerCase().includes(input.toLowerCase())
            }
            style={{ width: '100%' }}
          />
        );
      case 'RSVP_EVENT':
        return (
          <Select
            showSearch
            placeholder="Select event"
            options={eventOpts}
            value={step.targetId || undefined}
            onChange={(val) => onChange({ targetId: val })}
            filterOption={(input, option) =>
              (option?.label as string)?.toLowerCase().includes(input.toLowerCase())
            }
            style={{ width: '100%' }}
          />
        );
      case 'SIGNUP_SHIFT':
        return (
          <Select
            showSearch
            placeholder="Select shift"
            options={shiftOpts}
            value={step.targetId || undefined}
            onChange={(val) => onChange({ targetId: val })}
            filterOption={(input, option) =>
              (option?.label as string)?.toLowerCase().includes(input.toLowerCase())
            }
            style={{ width: '100%' }}
          />
        );
      case 'JOIN_CHALLENGE':
        return (
          <Select
            showSearch
            placeholder="Select challenge"
            options={challengeOpts}
            value={step.targetId || undefined}
            onChange={(val) => onChange({ targetId: val })}
            filterOption={(input, option) =>
              (option?.label as string)?.toLowerCase().includes(input.toLowerCase())
            }
            style={{ width: '100%' }}
          />
        );
      case 'VISIT_LINK':
      case 'CUSTOM':
        return (
          <Input
            placeholder="https://example.com"
            value={localTargetUrl}
            onChange={(e) => setLocalTargetUrl(e.target.value)}
            onBlur={() => onChange({ targetUrl: localTargetUrl || null })}
          />
        );
      default:
        return null;
    }
  };

  return (
    <Card size="small" style={{ background: 'rgba(255,255,255,0.02)' }}>
      <Space direction="vertical" size="small" style={{ width: '100%' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
          <Tag>{index + 1}</Tag>
          <Select
            value={step.kind}
            onChange={(val) => onChange({ kind: val, targetId: null, targetUrl: null })}
            style={{ width: 220 }}
            options={KIND_OPTIONS.map((opt) => ({ value: opt.value, label: (<Space>{opt.icon}<span>{opt.label}</span></Space>) }))}
          />
          <div style={{ marginLeft: 'auto', display: 'flex', gap: 4 }}>
            <Button
              size="small"
              icon={<ArrowUpOutlined />}
              disabled={index === 0}
              onClick={onMoveUp}
            />
            <Button
              size="small"
              icon={<ArrowDownOutlined />}
              disabled={index === total - 1}
              onClick={onMoveDown}
            />
            <Popconfirm title="Delete this step?" onConfirm={onDelete}>
              <Button size="small" danger icon={<DeleteOutlined />} />
            </Popconfirm>
          </div>
        </div>

        <Input
          placeholder="Step label"
          value={localLabel}
          onChange={(e) => setLocalLabel(e.target.value)}
          onBlur={() => {
            if (localLabel !== step.label) onChange({ label: localLabel });
          }}
        />

        <Input.TextArea
          placeholder="Optional description"
          rows={2}
          value={localDescription}
          onChange={(e) => setLocalDescription(e.target.value)}
          onBlur={() => {
            if (localDescription !== (step.description || '')) {
              onChange({ description: localDescription || null });
            }
          }}
        />

        {renderPicker()}
      </Space>
    </Card>
  );
}
