import { DepartmentKey } from "@prisma/client";
import type {
  BrandPulse,
  BrandRating,
  Employee,
  Initiative,
  InitiativeStatus,
  InitiativeType,
  Milestone,
  MilestoneStatus,
  MarketingRole,
  OpinionPublica,
  SocialSnapshot,
  Task,
  TaskStatus,
} from "@/lib/marketing/types";
import { marketingLocations, marketingSocialSnapshots } from "@/lib/marketing/mock";
import { resolveHighestUserRole } from "@/lib/role-resolution";

export const MARKETING_LOCATION_IDS = marketingLocations.map((location) => location.id);

function isLeaderRole(role: string | undefined): boolean {
  return role === "leader" || role === "lead";
}

export function toMarketingRole(role: string | undefined): MarketingRole {
  if (role === "owner") {
    return "owner";
  }

  if (isLeaderRole(role)) {
    return "lead";
  }

  return "employee";
}

export function canAccessMarketing(role: string | undefined, department: string | null | undefined): boolean {
  return role === "owner" || department === DepartmentKey.marketing;
}

export function canManageMarketing(role: string | undefined, department: string | null | undefined): boolean {
  if (role === "owner") {
    return true;
  }

  return isLeaderRole(role) && department === DepartmentKey.marketing;
}

export function clampBrandRating(value: number): BrandRating {
  if (value <= 1) {
    return 1;
  }

  if (value >= 5) {
    return 5;
  }

  return Math.round(value) as BrandRating;
}

function resolveActualValue(manualValue: number, autoValue?: number | null): number {
  const manual = Number.isFinite(manualValue) ? manualValue : 0;
  const auto = typeof autoValue === "number" && Number.isFinite(autoValue) ? autoValue : null;
  if (Math.abs(manual) > 0.0001) {
    return manual;
  }

  return auto ?? manual;
}

function clampOpinion(value: string): OpinionPublica {
  if (value === "positive" || value === "mixed" || value === "negative") {
    return value;
  }

  return "mixed";
}

function clampInitiativeType(value: string): InitiativeType {
  if (value === "evento" || value === "campania" || value === "cambio" || value === "implementacion" || value === "otro") {
    return value;
  }

  return "otro";
}

function clampInitiativeStatus(value: string): InitiativeStatus {
  if (value === "planning" || value === "in_progress" || value === "completion" || value === "results" || value === "evaluation") {
    return value;
  }

  return "planning";
}

function clampTaskStatus(value: string): TaskStatus {
  if (value === "todo" || value === "in_progress" || value === "blocked" || value === "done") {
    return value;
  }

  return "todo";
}

function clampMilestoneStatus(value: string): MilestoneStatus {
  if (value === "pending" || value === "in_progress" || value === "completed") {
    return value;
  }

  return "pending";
}

export function mapMarketingEmployee(user: {
  id: string;
  name: string | null;
  email: string;
  departmentRole: string | null;
  userRoles: Array<{ role: { key: string } }>;
}): Employee {
  const roleKey = resolveHighestUserRole(user.userRoles.map((entry) => entry.role.key));
  const roleTitle = user.departmentRole?.trim() || (roleKey === "leader" ? "Lider de Marketing" : "Empleado de Marketing");

  return {
    id: user.id,
    name: user.name?.trim() || user.email,
    roleTitle,
    locationIds: MARKETING_LOCATION_IDS,
    isLead: roleKey === "leader",
  };
}

export function mapMarketingTask(task: {
  id: string;
  initiativeId: string;
  title: string;
  description: string;
  assigneeId: string | null;
  status: string;
  dueDate: Date;
  updatedAt: Date;
  evidenceLinks: Array<{ url: string }>;
}): Task {
  return {
    id: task.id,
    initiativeId: task.initiativeId,
    title: task.title,
    description: task.description,
    assigneeId: task.assigneeId ?? "",
    status: clampTaskStatus(task.status),
    dueDate: task.dueDate.toISOString().slice(0, 10),
    updatedAt: task.updatedAt.toISOString(),
    evidenceLinks: task.evidenceLinks.map((item) => item.url),
  };
}

export function mapMarketingInitiative(initiative: {
  id: string;
  name: string;
  type: string;
  status: string;
  isGlobal: boolean;
  ownerId: string | null;
  dueDate: Date;
  completedAt: Date | null;
  importanceWeight: number;
  leadRating1to5: number;
  trackScore: boolean;
  trackTickets: boolean;
  trackRevenue: boolean;
  target: number;
  actual: number;
  ticketsTarget: number;
  ticketsActual: number;
  revenueTarget: number;
  revenueActual: number;
  opinionPublica: string;
  queFunciono: string;
  queNo: string;
  proximoIntento: string;
  updatedByName: string | null;
  updatedAt: Date;
  attributionChannel?: string | null;
  attributionPageId?: string | null;
  attributionCampaign?: string | null;
  attributionStart?: Date | null;
  attributionEnd?: Date | null;
  autoActual?: number | null;
  autoTicketsActual?: number | null;
  autoRevenueActual?: number | null;
  autoUpdatedAt?: Date | null;
  contributors: Array<{ userId: string }>;
  locations: Array<{ locationId: string }>;
  evidenceLinks: Array<{ url: string }>;
  tasks: Array<{ id: string }>;
  milestones?: Array<{
    id: string;
    initiativeId: string;
    title: string;
    description: string;
    dueDate: Date;
    status: string;
    sortOrder: number;
    checkpoints: Array<{
      id: string;
      note: string;
      createdAt: Date;
      createdByName: string | null;
    }>;
  }>;
}): Initiative {
  return {
    id: initiative.id,
    name: initiative.name,
    type: clampInitiativeType(initiative.type),
    status: clampInitiativeStatus(initiative.status),
    isGlobal: initiative.isGlobal,
    locationIds: initiative.locations.map((item) => item.locationId),
    ownerId: initiative.ownerId ?? "",
    contributorIds: initiative.contributors.map((item) => item.userId),
    dueDate: initiative.dueDate.toISOString().slice(0, 10),
    completedAt: initiative.completedAt ? initiative.completedAt.toISOString().slice(0, 10) : null,
    importanceWeight: initiative.importanceWeight,
    leadRating1to5: clampBrandRating(initiative.leadRating1to5),
    metricSelection: {
      score: initiative.trackScore,
      tickets: initiative.trackTickets,
      revenue: initiative.trackRevenue,
    },
    metrics: {
      target: initiative.target,
      actual: resolveActualValue(initiative.actual, initiative.autoActual),
      ticketsTarget: initiative.ticketsTarget,
      ticketsActual: resolveActualValue(initiative.ticketsActual, initiative.autoTicketsActual),
      revenueTarget: initiative.revenueTarget,
      revenueActual: resolveActualValue(initiative.revenueActual, initiative.autoRevenueActual),
    },
    attributionChannel: initiative.attributionChannel === "facebook" || initiative.attributionChannel === "instagram"
      ? initiative.attributionChannel
      : null,
    attributionPageId: initiative.attributionPageId,
    attributionCampaign: initiative.attributionCampaign,
    attributionStart: initiative.attributionStart ? initiative.attributionStart.toISOString().slice(0, 10) : null,
    attributionEnd: initiative.attributionEnd ? initiative.attributionEnd.toISOString().slice(0, 10) : null,
    autoActual: initiative.autoActual,
    autoTicketsActual: initiative.autoTicketsActual,
    autoRevenueActual: initiative.autoRevenueActual,
    autoUpdatedAt: initiative.autoUpdatedAt ? initiative.autoUpdatedAt.toISOString() : null,
    retro: {
      opinionPublica: clampOpinion(initiative.opinionPublica),
      queFunciono: initiative.queFunciono,
      queNo: initiative.queNo,
      proximoIntento: initiative.proximoIntento,
    },
    evidenceLinks: initiative.evidenceLinks.map((item) => item.url),
    taskIds: initiative.tasks.map((task) => task.id),
    updatedByName: initiative.updatedByName,
    updatedAt: initiative.updatedAt.toISOString(),
    milestones: (initiative.milestones ?? []).map((milestone) => ({
      id: milestone.id,
      initiativeId: milestone.initiativeId,
      title: milestone.title,
      description: milestone.description,
      dueDate: milestone.dueDate.toISOString().slice(0, 10),
      status: clampMilestoneStatus(milestone.status),
      sortOrder: milestone.sortOrder,
      checkpoints: milestone.checkpoints.map((checkpoint) => ({
        id: checkpoint.id,
        note: checkpoint.note,
        createdAt: checkpoint.createdAt.toISOString(),
        createdByName: checkpoint.createdByName,
      })),
    })),
  };
}

export function mapMarketingMilestone(milestone: {
  id: string;
  initiativeId: string;
  title: string;
  description: string;
  dueDate: Date;
  status: string;
  sortOrder: number;
  checkpoints: Array<{
    id: string;
    note: string;
    createdAt: Date;
    createdByName: string | null;
  }>;
}): Milestone {
  return {
    id: milestone.id,
    initiativeId: milestone.initiativeId,
    title: milestone.title,
    description: milestone.description,
    dueDate: milestone.dueDate.toISOString().slice(0, 10),
    status: clampMilestoneStatus(milestone.status),
    sortOrder: milestone.sortOrder,
    checkpoints: milestone.checkpoints.map((checkpoint) => ({
      id: checkpoint.id,
      note: checkpoint.note,
      createdAt: checkpoint.createdAt.toISOString(),
      createdByName: checkpoint.createdByName,
    })),
  };
}

export function mapSocialSnapshot(snapshot: {
  id: string;
  channel: string;
  range: string;
  followersStart: number;
  followersEnd: number;
  engagementRate: number;
  reach: number;
  impressions: number;
  capturedAt: Date;
}): SocialSnapshot {
  return {
    id: snapshot.id,
    channel: snapshot.channel === "facebook" ? "facebook" : "instagram",
    range: snapshot.range === "30d" ? "30d" : "7d",
    followersStart: snapshot.followersStart,
    followersEnd: snapshot.followersEnd,
    engagementRate: snapshot.engagementRate,
    reach: snapshot.reach,
    impressions: snapshot.impressions,
    capturedAt: snapshot.capturedAt.toISOString(),
  };
}

export function mapBrandPulse(pulse: {
  id: string;
  month: string;
  rating1to5: number;
  notes: string;
  updatedAt: Date;
  updatedById: string | null;
  updatedByName: string | null;
}): BrandPulse {
  return {
    id: pulse.id,
    month: pulse.month,
    rating1to5: clampBrandRating(pulse.rating1to5),
    notes: pulse.notes,
    updatedAt: pulse.updatedAt.toISOString(),
    updatedById: pulse.updatedById ?? "",
    updatedByName: pulse.updatedByName,
  };
}

export function getDefaultSocialSnapshots(): SocialSnapshot[] {
  return marketingSocialSnapshots;
}
