import { z } from "zod";
import {
  autodiagnosticSectionIds,
  managerialLevels,
} from "@/lib/autodiagnostic-shared";
import { TRAINING_MESSAGE_MAX_LENGTH } from "@/lib/training";
import { metricIds } from "@/lib/types";

const metricIdSchema = z.enum(metricIds);
const difficultySchema = z.enum([
  "Fondamentaux",
  "Intermédiaire",
  "Intermediaire",
  "Exigeant",
]);
const catalogStatusSchema = z.enum(["draft", "published", "archived"]);
const clientStatusSchema = z.enum(["active", "archived"]);
const tagStatusSchema = z.enum(["active", "archived"]);
const knowledgeDocumentStatusSchema = z.enum(["processing", "ready", "failed"]);
const conversationStatusSchema = z.enum([
  "ongoing",
  "resolved",
  "escalated",
  "max_turns",
  "manual_end",
]);
const conversationOutcomeSchema = z.enum([
  "resolved",
  "escalated",
  "max_turns",
  "manual_end",
]);

export const ChatMessageSchema = z.object({
  id: z.string().min(1),
  role: z.enum(["assistant", "user"]),
  content: z.string().min(1),
  createdAt: z.string().min(1),
});

export const EmployeeProfileSchema = z.object({
  name: z.string().min(1).max(120),
  role: z.string().min(1).max(120),
  team: z.string().min(1).max(120),
  seniority: z.string().min(1).max(120),
  currentMood: z.string().min(1).max(180),
});

const RawMetricSchema = z.object({
  id: metricIdSchema,
  score: z.number().min(0).max(100),
  rationale: z.string().min(1).max(220),
});

export const ScenarioDefinitionSchema = z.object({
  id: z.string().min(1).max(120),
  title: z.string().min(1).max(180),
  targetSkill: z.string().min(1).max(120),
  difficulty: difficultySchema,
  durationLabel: z.string().min(1).max(120),
  shortBrief: z.string().min(1).max(1200),
  employeeProfile: EmployeeProfileSchema,
  openingMessage: z.string().min(1).max(1200),
  managerGoal: z.string().min(1).max(600),
  successSignals: z.array(z.string().min(1).max(220)).min(1).max(10),
  failureSignals: z.array(z.string().min(1).max(220)).min(1).max(10),
  completionRules: z.array(z.string().min(1).max(220)).min(1).max(10),
  metricWeights: z.object({
    empathy: z.number().min(0).max(3),
    clarity: z.number().min(0).max(3),
    questioning: z.number().min(0).max(3),
    deescalation: z.number().min(0).max(3),
    accountability: z.number().min(0).max(3),
    action_alignment: z.number().min(0).max(3),
  }),
  maxTurns: z.number().int().min(1).max(20),
  tensionColor: z.string().regex(/^#[0-9A-Fa-f]{6}$/),
});

export const RoleplayResponseSchema = z.object({
  assistantMessage: z.string().min(1).max(900),
  conversationStatus: conversationStatusSchema,
  reason: z.string().min(1).max(220),
});

export const LiveEvaluationSchema = z.object({
  metrics: z.array(RawMetricSchema).length(metricIds.length),
  coachingNote: z.string().min(1).max(320),
  riskFlags: z.array(z.string().min(1).max(120)).max(3),
  learnerSignal: z.string().min(1).max(180),
});

export const FinalAssessmentSchema = z.object({
  outcome: conversationOutcomeSchema,
  summary: z.string().min(1).max(700),
  readiness: z.string().min(1).max(220),
  metricSummary: z.array(RawMetricSchema).length(metricIds.length),
  strengths: z.array(z.string().min(1).max(220)).min(3).max(4),
  missedOpportunities: z.array(z.string().min(1).max(220)).min(3).max(4),
  turningPoints: z.array(z.string().min(1).max(220)).min(3).max(4),
  actionPlan: z.array(z.string().min(1).max(220)).min(3).max(4),
  closingAdvice: z.string().min(1).max(220),
});

export const DemoAppConfigSchema = z.object({
  appName: z.string().trim().min(1).max(120),
  loginTitle: z.string().trim().min(1).max(200),
  loginDescription: z.string().trim().min(1).max(700),
  demoUser: z.object({
    email: z.email(),
    fullName: z.string().trim().min(1).max(120),
    companyLabel: z.string().trim().min(1).max(160),
  }),
  coach: z.object({
    name: z.string().trim().min(1).max(120),
  }),
});

export const DemoScenarioSchema = ScenarioDefinitionSchema.omit({
  durationLabel: true,
  tensionColor: true,
}).extend({
  tags: z.array(z.string().trim().min(1).max(120)).max(8).default([]),
});

export const DemoScenarioFileSchema = z.object({
  scenarios: z.array(DemoScenarioSchema).min(1),
});

export const DemoKnowledgeEntrySchema = z.object({
  id: z.string().trim().min(1).max(120),
  title: z.string().trim().min(1).max(200),
  sourceLabel: z.string().trim().min(1).max(200).nullable().optional(),
  content: z.string().trim().min(1).max(10000),
  tags: z.array(z.string().trim().min(1).max(120)).default([]),
});

export const DemoKnowledgeFileSchema = z.object({
  entries: z.array(DemoKnowledgeEntrySchema).default([]),
});

export const CreateSessionRequestSchema = z.object({
  scenarioId: z.string().min(1),
});

export const TurnRequestSchema = z.object({
  sessionId: z.string().uuid(),
  userMessage: z.string().min(1).max(TRAINING_MESSAGE_MAX_LENGTH),
});

export const FinalizeRequestSchema = z.object({
  sessionId: z.string().uuid(),
  conversationStatus: conversationOutcomeSchema.optional(),
});

export const MagicLinkRequestSchema = z.object({
  email: z.email(),
});

export const DemoAccessRequestSchema = z.object({
  password: z.string().min(1).max(200),
  next: z.string().optional(),
});

const managerialLevelSchema = z.enum(managerialLevels);
const autodiagnosticDraftAnswerValueSchema = z.enum(["", "A", "B", "C", "D"]);

export const OnboardingAnswersSchema = z.object({
  industrySector: z.string().trim().min(1).max(200),
  department: z.string().trim().min(1).max(200),
  jobTitle: z.string().trim().min(1).max(200),
  managerialLevel: managerialLevelSchema,
  companySize: z.string().trim().min(1).max(200),
  companyContext: z.string().trim().min(1).max(600),
  workMode: z.string().trim().min(1).max(600),
});

export const AutodiagnosticSectionScoreSchema = z.object({
  id: z.enum(autodiagnosticSectionIds),
  title: z.string().trim().min(1).max(120),
  score: z.number().min(0).max(100),
});

export const AutodiagnosticResultSchema = z.object({
  managerialLevel: managerialLevelSchema,
  globalScore: z.number().min(0).max(100),
  overallLabel: z.string().trim().min(1).max(120),
  summary: z.string().trim().min(1).max(1200),
  strengths: z.array(z.string().trim().min(1).max(220)).length(2),
  attentionPoints: z.array(z.string().trim().min(1).max(220)).length(2),
  sectionScores: z.array(AutodiagnosticSectionScoreSchema).length(6),
});

export const OnboardingUpdateSchema = z.object({
  answers: OnboardingAnswersSchema.partial().optional(),
  actionPlanPrompt: z.string().trim().max(12000).optional(),
  autodiagnosticAnswers: z
    .record(z.string(), autodiagnosticDraftAnswerValueSchema)
    .optional(),
  autodiagnosticResult: AutodiagnosticResultSchema.nullable().optional(),
  autodiagnosticPromptContext: z.string().trim().max(12000).optional(),
  completeOnboarding: z.boolean().optional(),
  completeActionPlan: z.boolean().optional(),
  completeAutodiagnostic: z.boolean().optional(),
  acknowledgeAutodiagnosticResult: z.boolean().optional(),
});

export const ActionPlanSuggestionObjectiveSchema = z.object({
  objectiveLabel: z.string().trim().min(1).max(220),
  whatToDo: z.string().trim().min(1).max(400),
  howAndWithWhom: z.string().trim().min(1).max(400),
  when: z.string().trim().min(1).max(220),
  successCriteria: z.string().trim().min(1).max(400),
  pointOfAttention: z.string().trim().min(1).max(280),
});

export const ActionPlanSuggestionRequestSchema = z.object({
  answers: OnboardingAnswersSchema,
  autodiagnosticResult: AutodiagnosticResultSchema,
});

export const ActionPlanSuggestionResponseSchema = z.object({
  objectives: z.array(ActionPlanSuggestionObjectiveSchema).length(3),
});

export const CoachSourceSchema = z.object({
  id: z.string().min(1).max(120),
  kind: z.enum(["knowledge", "profile", "report", "system"]),
  label: z.string().min(1).max(200),
  detail: z.string().min(1).max(2000),
  similarity: z.number().min(0).max(1).nullable().optional(),
  documentId: z.string().uuid().nullable().optional(),
  chunkId: z.string().uuid().nullable().optional(),
});

const DemoCoachMessageSchema = z.object({
  id: z.string().min(1),
  conversationId: z.string().min(1),
  role: z.enum(["assistant", "user"]),
  content: z.string().min(1),
  createdAt: z.string().min(1),
  sources: z.array(CoachSourceSchema).default([]),
});

export const DemoTurnRequestSchema = z.object({
  sessionId: z.string().uuid(),
  scenario: ScenarioDefinitionSchema,
  transcript: z.array(ChatMessageSchema),
  liveEvaluations: z.array(LiveEvaluationSchema),
  userTurns: z.number().int().min(0).max(99),
  status: conversationStatusSchema,
  userMessage: z.string().min(1).max(TRAINING_MESSAGE_MAX_LENGTH),
});

export const DemoFinalizeRequestSchema = z.object({
  scenario: ScenarioDefinitionSchema,
  transcript: z.array(ChatMessageSchema),
  liveEvaluations: z.array(LiveEvaluationSchema),
  currentStatus: conversationStatusSchema,
  conversationStatus: conversationOutcomeSchema.optional(),
});

export const DemoRecentSessionContextSchema = z.object({
  scenarioTitle: z.string().min(1).max(180),
  scenarioTargetSkill: z.string().min(1).max(120),
  status: conversationStatusSchema,
  updatedAt: z.string().min(1),
  finalAssessment: z
    .object({
      summary: z.string().min(1).max(700),
      readiness: z.string().min(1).max(220),
      actionPlan: z.array(z.string().min(1).max(220)).min(1).max(4),
    })
    .nullable(),
});

export const DemoCoachReplyRequestSchema = z.object({
  conversationId: z.string().min(1).max(120),
  history: z.array(DemoCoachMessageSchema).max(40),
  userMessage: z.string().trim().min(1).max(4000),
  onboardingPromptContext: z.string().max(4000),
  actionPlanPrompt: z.string().max(12000),
  recentSessions: z.array(DemoRecentSessionContextSchema).max(5),
});

export const CreateCoachConversationSchema = z.object({
  title: z.string().trim().min(1).max(160).optional(),
});

export const CreateCoachMessageSchema = z.object({
  content: z.string().trim().min(1).max(4000),
});

export const KnowledgeDocumentUploadSchema = z.object({
  title: z.string().trim().min(1).max(200).optional(),
  sourceLabel: z.string().trim().min(1).max(200).optional(),
});

export const KnowledgeDocumentRecordSchema = z.object({
  id: z.string().uuid(),
  title: z.string().min(1).max(200),
  sourceLabel: z.string().nullable(),
  fileName: z.string().min(1).max(260),
  contentType: z.string().min(1).max(120),
  fileSize: z.number().nonnegative(),
  status: knowledgeDocumentStatusSchema,
  chunkCount: z.number().int().nonnegative(),
  contentLength: z.number().int().nonnegative(),
  errorMessage: z.string().nullable(),
  createdAt: z.string().min(1),
  updatedAt: z.string().min(1),
});

export const ScenarioMutationSchema = ScenarioDefinitionSchema.omit({
  id: true,
  durationLabel: true,
  tensionColor: true,
}).extend({
  templateId: z.string().uuid().optional(),
  tagIds: z.array(z.string().uuid()).default([]),
});

export const ScenarioActionSchema = z.discriminatedUnion("action", [
  z.object({
    action: z.literal("create"),
    payload: ScenarioMutationSchema,
  }),
  z.object({
    action: z.literal("saveDraft"),
    payload: ScenarioMutationSchema.extend({
      templateId: z.string().uuid(),
    }),
  }),
  z.object({
    action: z.literal("publish"),
    templateId: z.string().uuid(),
  }),
  z.object({
    action: z.literal("archive"),
    templateId: z.string().uuid(),
  }),
]);

const GroupMutationCoreSchema = z.object({
  id: z.string().uuid().optional(),
  name: z.string().min(1).max(160),
  description: z.string().max(800).nullable().optional(),
  status: catalogStatusSchema,
  companyId: z.string().uuid(),
  accessStartsAt: z.string().datetime({ offset: true }).nullable().optional(),
  accessEndsAt: z.string().datetime({ offset: true }).nullable().optional(),
  tagIds: z.array(z.string().uuid()).default([]),
  scenarioTemplateIds: z.array(z.string().uuid()).default([]),
});

function withGroupAccessWindowValidation<
  T extends z.ZodObject<Record<string, z.ZodType<unknown>>>,
>(schema: T) {
  return schema.refine(
    (value: { accessStartsAt?: string | null; accessEndsAt?: string | null }) =>
      !value.accessStartsAt ||
      !value.accessEndsAt ||
      new Date(value.accessStartsAt).getTime() <=
        new Date(value.accessEndsAt).getTime(),
    {
      message:
        "La date de fin doit etre posterieure ou egale a la date de debut.",
      path: ["accessEndsAt"],
    },
  );
}

export const GroupMutationSchema = withGroupAccessWindowValidation(
  GroupMutationCoreSchema,
);

export const GroupActionSchema = z.discriminatedUnion("action", [
  z.object({
    action: z.literal("create"),
    payload: withGroupAccessWindowValidation(
      GroupMutationCoreSchema.omit({ id: true }),
    ),
  }),
  z.object({
    action: z.literal("update"),
    payload: withGroupAccessWindowValidation(
      GroupMutationCoreSchema.extend({
        id: z.string().uuid(),
      }),
    ),
  }),
  z.object({
    action: z.literal("archive"),
    groupId: z.string().uuid(),
  }),
]);

export const TagMutationSchema = z.object({
  id: z.string().uuid().optional(),
  label: z.string().min(1).max(120),
  slug: z.string().min(1).max(120).regex(/^[a-z0-9-]+$/),
  status: tagStatusSchema,
});

export const TagActionSchema = z.discriminatedUnion("action", [
  z.object({
    action: z.literal("create"),
    payload: TagMutationSchema.omit({ id: true }),
  }),
  z.object({
    action: z.literal("update"),
    payload: TagMutationSchema.extend({
      id: z.string().uuid(),
    }),
  }),
  z.object({
    action: z.literal("delete"),
    tagId: z.string().uuid(),
  }),
]);

export const ClientMutationSchema = z.object({
  id: z.string().uuid().optional(),
  name: z.string().min(1).max(160),
  slug: z.string().min(1).max(120).regex(/^[a-z0-9-]+$/),
  status: clientStatusSchema,
});

export const ClientActionSchema = z.discriminatedUnion("action", [
  z.object({
    action: z.literal("create"),
    payload: ClientMutationSchema.omit({ id: true }),
  }),
  z.object({
    action: z.literal("update"),
    payload: ClientMutationSchema.extend({
      id: z.string().uuid(),
    }),
  }),
  z.object({
    action: z.literal("archive"),
    clientId: z.string().uuid(),
  }),
]);

export const AccessActionSchema = z.object({
  clientId: z.string().uuid(),
  groupIds: z.array(z.string().uuid()).default([]),
  scenarioTemplateIds: z.array(z.string().uuid()).default([]),
});

export const GroupMemberActionSchema = z.discriminatedUnion("action", [
  z.object({
    action: z.literal("add"),
    groupId: z.string().uuid(),
    emails: z.array(z.email()).min(1),
  }),
  z.object({
    action: z.literal("importCsv"),
    groupId: z.string().uuid(),
    fileName: z.string().min(1),
    csvContent: z.string().min(1),
  }),
  z.object({
    action: z.literal("remove"),
    groupId: z.string().uuid(),
    companyMemberId: z.string().uuid(),
  }),
]);

const uuidListSchema = z.array(z.string().uuid()).min(1);

const ScenarioBulkChangesSchema = z
  .object({
    status: catalogStatusSchema.optional(),
    difficulty: difficultySchema.optional(),
    addTagIds: z.array(z.string().uuid()).default([]),
    removeTagIds: z.array(z.string().uuid()).default([]),
  })
  .refine(
    (value) =>
      Boolean(value.status) ||
      Boolean(value.difficulty) ||
      value.addTagIds.length > 0 ||
      value.removeTagIds.length > 0,
    {
      message: "Aucune modification en masse n'a ete fournie.",
    },
  );

const GroupBulkChangesSchema = z
  .object({
    status: catalogStatusSchema.optional(),
    addTagIds: z.array(z.string().uuid()).default([]),
    removeTagIds: z.array(z.string().uuid()).default([]),
  })
  .refine(
    (value) =>
      Boolean(value.status) ||
      value.addTagIds.length > 0 ||
      value.removeTagIds.length > 0,
    {
      message: "Aucune modification en masse n'a ete fournie.",
    },
  );

const ClientBulkChangesSchema = z
  .object({
    status: clientStatusSchema,
  })
  .refine((value) => Boolean(value.status), {
    message: "Aucune modification en masse n'a ete fournie.",
  });

export const AdminBulkActionSchema = z.discriminatedUnion("entity", [
  z.object({
    entity: z.literal("scenarios"),
    ids: uuidListSchema,
    changes: ScenarioBulkChangesSchema,
  }),
  z.object({
    entity: z.literal("groups"),
    ids: uuidListSchema,
    changes: GroupBulkChangesSchema,
  }),
  z.object({
    entity: z.literal("clients"),
    ids: uuidListSchema,
    changes: ClientBulkChangesSchema,
  }),
]);
