import React, { useEffect, useMemo, useState } from "react";
import { bpFetch } from "../api/client";
import SmartVariablesDrawer from "../components/SmartVariablesDrawer";
import { Drawer } from "../ui/Drawer";

const EVENT_LABELS = {
  booking_created: "Booking Created",
  booking_updated: "Booking Updated",
  booking_confirmed: "Booking Confirmed",
  booking_cancelled: "Booking Cancelled",
  booking_abandoned: "Booking Abandoned",
  customer_created: "Customer Created",
};

const FALLBACK_ACTION_TYPES = {
  send_email: {
    label: "Send email",
    default_config: {
      to: "{{customer_email}}",
      from_name: "{{site_name}}",
      from_email: "{{admin_email}}",
      subject: "Booking notification #{{booking_id}}",
      body: "<p>{{service_name}} - {{start_date}} {{start_time}}</p>",
      attach_ics: false,
    },
    fields: [
      { key: "to", label: "To", type: "text" },
      { key: "subject", label: "Subject", type: "text" },
      { key: "from_name", label: "From name", type: "text" },
      { key: "from_email", label: "From email", type: "text" },
      { key: "body", label: "Body (HTML)", type: "textarea", rows: 6 },
      { key: "attach_ics", label: "Attach ICS calendar file", type: "checkbox" },
    ],
  },
};

const CONDITION_FIELDS = [
  { value: "booking_status", label: "Booking status" },
  { value: "service_name", label: "Service name" },
  { value: "agent_name", label: "Agent name" },
  { value: "customer_email", label: "Customer email" },
  { value: "customer_phone", label: "Customer phone" },
  { value: "total", label: "Total" },
  { value: "promo_code", label: "Promo code" },
];

const CONDITION_OPERATORS = [
  { value: "equals", label: "Equals" },
  { value: "not_equals", label: "Does not equal" },
  { value: "contains", label: "Contains" },
  { value: "not_contains", label: "Does not contain" },
  { value: "empty", label: "Is empty" },
  { value: "not_empty", label: "Is not empty" },
  { value: "greater_than", label: "Greater than" },
  { value: "less_than", label: "Less than" },
];

function normalizeConditions(input) {
  const source = input && typeof input === "object" ? input : {};
  const match = source.match === "any" ? "any" : "all";
  const rules = Array.isArray(source.rules) ? source.rules : [];
  return {
    match,
    rules: rules.map((rule) => ({
      field: rule.field || "booking_status",
      operator: rule.operator || "equals",
      value: rule.value || "",
    })),
  };
}

function getDefaultConfig(type, actionTypes) {
  return { ...((actionTypes?.[type]?.default_config || {})) };
}

function getFieldValue(action, key, fallback = "") {
  if (!action?.config || !Object.prototype.hasOwnProperty.call(action.config, key)) {
    return fallback;
  }
  return action.config[key];
}

function FieldInput({ field, action, onChange }) {
  const key = field.key;
  const type = field.type || "text";
  const value = getFieldValue(action, key, type === "checkbox" ? false : "");

  if (type === "checkbox") {
    return (
      <label className="bp-check" style={{ marginTop: 8 }}>
        <input type="checkbox" checked={!!value} onChange={(event) => onChange(key, event.target.checked)} />
        {field.label || key}
      </label>
    );
  }

  if (type === "textarea") {
    return (
      <div className="bp-settings-field" style={{ marginTop: 12 }}>
        <label className="bp-label">{field.label || key}</label>
        <textarea
          className="bp-textarea"
          rows={field.rows || 5}
          value={value || ""}
          onChange={(event) => onChange(key, event.target.value)}
        />
      </div>
    );
  }

  if (type === "select") {
    const options = Array.isArray(field.options) ? field.options : [];
    return (
      <div className="bp-settings-field">
        <label className="bp-label">{field.label || key}</label>
        <select className="bp-input" value={value || ""} onChange={(event) => onChange(key, event.target.value)}>
          {options.map((option) => (
            <option key={option.value} value={option.value}>
              {option.label || option.value}
            </option>
          ))}
        </select>
      </div>
    );
  }

  return (
    <div className="bp-settings-field">
      <label className="bp-label">{field.label || key}</label>
      <input
        type={type === "password" ? "password" : type === "url" ? "url" : "text"}
        className="bp-input"
        value={value || ""}
        onChange={(event) => onChange(key, event.target.value)}
        autoComplete={type === "password" ? "new-password" : undefined}
      />
    </div>
  );
}

export default function WorkflowEditScreen({ workflowId, onClose, onSaved }) {
  const [workflow, setWorkflow] = useState(null);
  const [actions, setActions] = useState([]);
  const [meta, setMeta] = useState({ events: Object.keys(EVENT_LABELS), action_types: FALLBACK_ACTION_TYPES });
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [actionSavingId, setActionSavingId] = useState(null);
  const [error, setError] = useState("");
  const [toast, setToast] = useState("");
  const [showVariables, setShowVariables] = useState(false);
  const [addType, setAddType] = useState("send_email");

  const actionTypes = useMemo(
    () => (meta.action_types && Object.keys(meta.action_types).length ? meta.action_types : FALLBACK_ACTION_TYPES),
    [meta]
  );

  const actionTypeKeys = useMemo(() => Object.keys(actionTypes), [actionTypes]);
  const eventOptions = useMemo(() => meta.events || Object.keys(EVENT_LABELS), [meta]);

  useEffect(() => {
    if (!workflowId) return;
    loadWorkflow();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [workflowId]);

  useEffect(() => {
    if (!toast) return undefined;
    const timeout = window.setTimeout(() => setToast(""), 2600);
    return () => window.clearTimeout(timeout);
  }, [toast]);

  async function loadWorkflow() {
    setLoading(true);
    setError("");
    try {
      const [workflowResp, metaResp] = await Promise.all([
        bpFetch(`/admin/notifications/workflows/${workflowId}`),
        bpFetch("/admin/notifications/meta").catch(() => null),
      ]);
      if (metaResp?.data) {
        setMeta({
          events: metaResp.data.events || Object.keys(EVENT_LABELS),
          action_types: metaResp.data.action_types || FALLBACK_ACTION_TYPES,
        });
      }
      const data = workflowResp?.data || null;
      setWorkflow(
        data
          ? {
              ...data,
              is_conditional: Number(data.is_conditional || 0) === 1,
              has_time_offset: Number(data.has_time_offset || 0) === 1,
              conditions: normalizeConditions(data.conditions),
            }
          : null
      );
      setActions(data?.actions || []);
    } catch (err) {
      console.error(err);
      setError(err.message || "Failed to load workflow.");
    } finally {
      setLoading(false);
    }
  }

  async function saveWorkflow() {
    if (!workflow) return;
    setSaving(true);
    setError("");
    try {
      await bpFetch(`/admin/notifications/workflows/${workflowId}`, {
        method: "PUT",
        body: {
          name: workflow.name,
          status: workflow.status,
          event_key: workflow.event_key,
          is_conditional: !!workflow.is_conditional,
          conditions: normalizeConditions(workflow.conditions),
          has_time_offset: !!workflow.has_time_offset,
          time_offset_minutes: workflow.time_offset_minutes,
        },
      });
      setToast("Workflow saved.");
      onSaved?.();
      await loadWorkflow();
    } catch (err) {
      console.error(err);
      setError(err.message || "Unable to save workflow.");
    } finally {
      setSaving(false);
    }
  }

  function updateActionField(actionId, key, value) {
    setActions((prev) =>
      prev.map((action) =>
        action.id === actionId
          ? {
              ...action,
              config: {
                ...(action.config || {}),
                [key]: value,
              },
            }
          : action
      )
    );
  }

  function changeActionType(actionId, type) {
    setActions((prev) =>
      prev.map((action) =>
        action.id === actionId
          ? {
              ...action,
              type,
              config: getDefaultConfig(type, actionTypes),
            }
          : action
      )
    );
  }

  function updateCondition(index, key, value) {
    setWorkflow((prev) => {
      const conditions = normalizeConditions(prev?.conditions);
      const rules = conditions.rules.map((rule, ruleIndex) => (ruleIndex === index ? { ...rule, [key]: value } : rule));
      return { ...prev, conditions: { ...conditions, rules } };
    });
  }

  function addCondition() {
    setWorkflow((prev) => {
      const conditions = normalizeConditions(prev?.conditions);
      return {
        ...prev,
        conditions: {
          ...conditions,
          rules: [...conditions.rules, { field: "booking_status", operator: "equals", value: "pending" }],
        },
      };
    });
  }

  function removeCondition(index) {
    setWorkflow((prev) => {
      const conditions = normalizeConditions(prev?.conditions);
      return { ...prev, conditions: { ...conditions, rules: conditions.rules.filter((_, ruleIndex) => ruleIndex !== index) } };
    });
  }

  async function saveAction(action) {
    setActionSavingId(action.id);
    setError("");
    try {
      await bpFetch(`/admin/notifications/actions/${action.id}`, {
        method: "PUT",
        body: {
          type: action.type,
          status: action.status,
          config: action.config,
        },
      });
      setToast("Action saved.");
      onSaved?.();
      await loadWorkflow();
    } catch (err) {
      console.error(err);
      setError(err.message || "Failed to save action.");
    } finally {
      setActionSavingId(null);
    }
  }

  async function deleteAction(actionId) {
    setError("");
    try {
      await bpFetch(`/admin/notifications/actions/${actionId}`, { method: "DELETE" });
      setToast("Action removed.");
      onSaved?.();
      await loadWorkflow();
    } catch (err) {
      console.error(err);
      setError(err.message || "Failed to delete action.");
    }
  }

  async function testAction(actionId) {
    setError("");
    try {
      await bpFetch(`/admin/notifications/actions/${actionId}/test`, { method: "POST" });
      setToast("Test action triggered using latest booking.");
    } catch (err) {
      console.error(err);
      setError(err.message || "Test failed.");
    }
  }

  async function addAction() {
    if (!workflow) return;
    setError("");
    try {
      await bpFetch(`/admin/notifications/workflows/${workflowId}/actions`, {
        method: "POST",
        body: {
          type: addType,
          config: getDefaultConfig(addType, actionTypes),
        },
      });
      setToast("Action added.");
      onSaved?.();
      await loadWorkflow();
    } catch (err) {
      console.error(err);
      setError(err.message || "Could not add action.");
    }
  }

  const drawerTitle = workflow?.name || `Workflow #${workflowId || ""}`.trim() || "Workflow editor";
  const conditions = normalizeConditions(workflow?.conditions);
  const headerActions = workflow ? (
    <button type="button" className="bp-btn bp-btn-ghost" onClick={() => setShowVariables(true)}>
      Smart variables
    </button>
  ) : null;

  return (
    <>
      <Drawer
        open
        title={drawerTitle}
        subtitle="Configure events, conditions, delays, and actions."
        onClose={onClose}
        width="940px"
        headerActions={headerActions}
      >
        <div className="bp-workflow-editor">
          {loading ? <div className="bp-card bp-workflow-editor__loading">Loading workflow...</div> : null}
          {!loading && !workflow ? <div className="bp-error">{error || "Failed to load workflow."}</div> : null}
          {!loading && workflow ? (
            <>
              {toast ? <div className="bp-toast bp-toast-success">{toast}</div> : null}
              {error ? <div className="bp-error">{error}</div> : null}

              <div className="bp-grid bp-workflow-editor__formGrid">
                <div className="bp-settings-field">
                  <label className="bp-label">Workflow name</label>
                  <input className="bp-input" value={workflow.name || ""} onChange={(event) => setWorkflow({ ...workflow, name: event.target.value })} />
                </div>
                <div className="bp-settings-field">
                  <label className="bp-label">Event</label>
                  <select className="bp-input" value={workflow.event_key || "booking_created"} onChange={(event) => setWorkflow({ ...workflow, event_key: event.target.value })}>
                    {eventOptions.map((eventKey) => (
                      <option key={eventKey} value={eventKey}>
                        {EVENT_LABELS[eventKey] || eventKey}
                      </option>
                    ))}
                  </select>
                </div>
                <div className="bp-settings-field">
                  <label className="bp-label">Status</label>
                  <select className="bp-input" value={workflow.status || "active"} onChange={(event) => setWorkflow({ ...workflow, status: event.target.value })}>
                    <option value="active">Active</option>
                    <option value="disabled">Disabled</option>
                  </select>
                </div>
                <div className="bp-settings-field">
                  <label className="bp-label">Conditional</label>
                  <label className="bp-check">
                    <input type="checkbox" checked={!!workflow.is_conditional} onChange={(event) => setWorkflow({ ...workflow, is_conditional: event.target.checked })} />
                    Only trigger when rules match
                  </label>
                </div>
                <div className="bp-settings-field">
                  <label className="bp-label">Time offset</label>
                  <label className="bp-check">
                    <input type="checkbox" checked={!!workflow.has_time_offset} onChange={(event) => setWorkflow({ ...workflow, has_time_offset: event.target.checked })} />
                    Delay actions
                  </label>
                </div>
                {workflow.has_time_offset ? (
                  <div className="bp-settings-field">
                    <label className="bp-label">Delay (minutes)</label>
                    <input
                      type="number"
                      className="bp-input"
                      value={workflow.time_offset_minutes || 0}
                      min="0"
                      onChange={(event) => setWorkflow({ ...workflow, time_offset_minutes: Math.max(0, Number(event.target.value)) })}
                    />
                  </div>
                ) : null}
              </div>

              {workflow.is_conditional ? (
                <div className="bp-card bp-workflow-editor__conditions">
                  <div className="bp-workflow-editor__conditionsHead">
                    <div className="bp-section-title">Conditions</div>
                    <select
                      className="bp-input bp-workflow-editor__conditionsMatch"
                      value={conditions.match}
                      onChange={(event) => setWorkflow({ ...workflow, conditions: { ...conditions, match: event.target.value } })}
                    >
                      <option value="all">Match all</option>
                      <option value="any">Match any</option>
                    </select>
                  </div>
                  <div className="bp-workflow-editor__conditionsList">
                    {conditions.rules.map((rule, index) => (
                      <div key={index} className="bp-grid bp-workflow-editor__conditionRow">
                        <div className="bp-settings-field">
                          <label className="bp-label">Field</label>
                          <select className="bp-input" value={rule.field} onChange={(event) => updateCondition(index, "field", event.target.value)}>
                            {CONDITION_FIELDS.map((field) => (
                              <option key={field.value} value={field.value}>
                                {field.label}
                              </option>
                            ))}
                          </select>
                        </div>
                        <div className="bp-settings-field">
                          <label className="bp-label">Operator</label>
                          <select className="bp-input" value={rule.operator} onChange={(event) => updateCondition(index, "operator", event.target.value)}>
                            {CONDITION_OPERATORS.map((operator) => (
                              <option key={operator.value} value={operator.value}>
                                {operator.label}
                              </option>
                            ))}
                          </select>
                        </div>
                        <div className="bp-settings-field">
                          <label className="bp-label">Value</label>
                          <input className="bp-input" value={rule.value || ""} onChange={(event) => updateCondition(index, "value", event.target.value)} />
                        </div>
                        <button className="bp-chip bp-workflow-editor__conditionRemove" type="button" onClick={() => removeCondition(index)}>
                          Remove
                        </button>
                      </div>
                    ))}
                    <button className="bp-btn" type="button" onClick={addCondition}>
                      + Add condition
                    </button>
                  </div>
                </div>
              ) : null}

              <div className="bp-settings-actions bp-workflow-editor__toolbar">
                <button className="bp-btn bp-btn-primary" onClick={saveWorkflow} disabled={saving}>
                  {saving ? "Saving..." : "Save workflow"}
                </button>
                <select className="bp-input bp-workflow-editor__toolbarSelect" value={addType} onChange={(event) => setAddType(event.target.value)}>
                  {actionTypeKeys.map((type) => (
                    <option key={type} value={type}>
                      {actionTypes[type]?.label || type}
                    </option>
                  ))}
                </select>
                <button className="bp-btn" onClick={addAction}>
                  + Add action
                </button>
              </div>

              <div className="bp-workflow-editor__actionsList">
                {actions.map((action) => {
                  const currentType = actionTypes[action.type] ? action.type : "send_email";
                  const fields = actionTypes[currentType]?.fields || FALLBACK_ACTION_TYPES.send_email.fields;
                  return (
                    <div key={action.id} className="bp-card bp-workflow-editor__actionCard">
                      <div className="bp-workflow-editor__actionHead">
                        <div className="bp-workflow-editor__actionMeta">
                          <div className="bp-card-label bp-workflow-editor__actionLabel">Action #{action.id}</div>
                          <select className="bp-input bp-workflow-editor__actionType" value={currentType} onChange={(event) => changeActionType(action.id, event.target.value)}>
                            {actionTypeKeys.map((type) => (
                              <option key={type} value={type}>
                                {actionTypes[type]?.label || type}
                              </option>
                            ))}
                          </select>
                        </div>
                        <div className="bp-row-actions bp-workflow-editor__actionControls">
                          <select
                            className="bp-input bp-workflow-editor__actionStatus"
                            value={action.status === "disabled" ? "disabled" : "active"}
                            onChange={(event) => setActions((prev) => prev.map((item) => (item.id === action.id ? { ...item, status: event.target.value } : item)))}
                          >
                            <option value="active">Active</option>
                            <option value="disabled">Disabled</option>
                          </select>
                          <button className="bp-chip" onClick={() => saveAction(action)} disabled={actionSavingId === action.id}>
                            {actionSavingId === action.id ? "Saving..." : "Save"}
                          </button>
                          <button className="bp-chip" onClick={() => testAction(action.id)}>
                            Test
                          </button>
                          <button className="bp-chip" onClick={() => deleteAction(action.id)}>
                            Remove
                          </button>
                        </div>
                      </div>

                      <div className="bp-grid bp-workflow-editor__actionFields">
                        {fields
                          .filter((field) => field.type !== "textarea" && field.type !== "checkbox")
                          .map((field) => (
                            <FieldInput key={field.key} field={field} action={action} onChange={(key, value) => updateActionField(action.id, key, value)} />
                          ))}
                      </div>
                      {fields
                        .filter((field) => field.type === "textarea" || field.type === "checkbox")
                        .map((field) => (
                          <FieldInput key={field.key} field={field} action={action} onChange={(key, value) => updateActionField(action.id, key, value)} />
                        ))}
                    </div>
                  );
                })}
              </div>
            </>
          ) : null}
        </div>
      </Drawer>
      <SmartVariablesDrawer eventKey={workflow?.event_key || "booking_created"} open={showVariables} onClose={() => setShowVariables(false)} />
    </>
  );
}
