import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { ApiError } from "@/api/client";
import { sendContactMessage, type ContactPayload } from "@/api/contact";

export type ContactStatus = "idle" | "submitting" | "succeeded" | "failed";

interface ContactState {
  status: ContactStatus;
  error: string | null;
  /** Echoed back in the success message. */
  lastSubmission: { firstName: string; topic: string; email: string } | null;
}

const initialState: ContactState = { status: "idle", error: null, lastSubmission: null };

function extractErrorDetails(fieldErrors: unknown): string {
  if (!fieldErrors) return "";
  if (typeof fieldErrors === "string") return fieldErrors;

  const messages: string[] = [];

  const extract = (val: unknown) => {
    if (!val) return;
    if (typeof val === "string") {
      messages.push(val);
    } else if (Array.isArray(val)) {
      val.forEach(extract);
    } else if (typeof val === "object") {
      if ("message" in val && typeof (val as { message?: unknown }).message === "string") {
        messages.push((val as { message: string }).message);
      } else {
        Object.values(val as Record<string, unknown>).forEach(extract);
      }
    }
  };

  extract(fieldErrors);

  return messages.filter(Boolean).join("\n");
}

export const submitContactForm = createAsyncThunk<
  ContactState["lastSubmission"],
  ContactPayload,
  { rejectValue: string }
>("contact/submit", async (payload, { rejectWithValue }) => {
  try {
    await sendContactMessage(payload);
    return {
      firstName: payload.fn,
      topic: payload.t,
      email: payload.e,
    };
  } catch (error: any) {
    if (error instanceof ApiError) {
      const details = extractErrorDetails(error.fieldErrors);
      return rejectWithValue(
        details && details !== error.message
          ? `${error.message}\n\n${details}`
          : details || error.message,
      );
    }

    const responseData = error?.response?.data;
    if (responseData) {
      const message = responseData.message ?? error?.message ?? "Validation failed";
      const details = extractErrorDetails(responseData.errors);
      return rejectWithValue(
        details && details !== message ? `${message}\n\n${details}` : details || message,
      );
    }

    return rejectWithValue("Something went wrong while sending your message. Please try again.");
  }
});

const contactSlice = createSlice({
  name: "contact",
  initialState,
  reducers: {
    resetContact: () => initialState,
  },
  extraReducers: (builder) => {
    builder
      .addCase(submitContactForm.pending, (state) => {
        state.status = "submitting";
        state.error = null;
      })
      .addCase(submitContactForm.fulfilled, (state, action) => {
        state.status = "succeeded";
        state.lastSubmission = action.payload;
      })
      .addCase(submitContactForm.rejected, (state, action) => {
        state.status = "failed";
        state.error = action.payload ?? "Something went wrong.";
      });
  },
});

export const { resetContact } = contactSlice.actions;
export default contactSlice.reducer;
