import type { WorksmobileComparisonItem } from "../../../lib/adminApi";

export type WorksmobileComparisonFilter =
  | "works_only"
  | "baron_only"
  | "needs_update"
  | "matched";

export type WorksmobileComparisonSummary = {
  total: number;
  matched: number;
  needsUpdate: number;
  missingInWorksmobile: number;
  missingInBaron: number;
  missingExternalKey: number;
};

export type WorksmobileComparisonColumnKey =
  | "status"
  | "baronId"
  | "baron"
  | "baronOrg"
  | "worksmobileId"
  | "externalKey"
  | "worksmobileDomain"
  | "worksmobile"
  | "worksmobileOrg"
  | "manage";

export type WorksmobileComparisonColumnVisibility = Record<
  WorksmobileComparisonColumnKey,
  boolean
>;

export function getDefaultWorksmobileComparisonColumns(): WorksmobileComparisonColumnVisibility {
  return {
    status: true,
    baronId: false,
    baron: true,
    baronOrg: true,
    worksmobileId: false,
    externalKey: false,
    worksmobileDomain: true,
    worksmobile: true,
    worksmobileOrg: true,
    manage: true,
  };
}

export function summarizeWorksmobileComparison(
  rows: WorksmobileComparisonItem[],
): WorksmobileComparisonSummary {
  return rows.reduce<WorksmobileComparisonSummary>(
    (summary, row) => {
      if (row.status === "matched") {
        summary.matched += 1;
      } else if (row.status === "needs_update") {
        summary.needsUpdate += 1;
      } else if (row.status === "missing_in_worksmobile") {
        summary.missingInWorksmobile += 1;
      } else if (row.status === "missing_in_baron") {
        summary.missingInBaron += 1;
      } else if (row.status === "missing_external_key") {
        summary.missingExternalKey += 1;
      }
      return summary;
    },
    {
      total: rows.length,
      matched: 0,
      needsUpdate: 0,
      missingInWorksmobile: 0,
      missingInBaron: 0,
      missingExternalKey: 0,
    },
  );
}

export function getWorksmobileComparisonStatusLabel(status: string) {
  switch (status) {
    case "matched":
      return "일치";
    case "missing_in_worksmobile":
      return "WORKS 없음";
    case "needs_update":
      return "업데이트 필요";
    case "missing_in_baron":
      return "Baron 없음";
    case "missing_external_key":
      return "ex_key 없음";
    default:
      return status;
  }
}

export function canCreateWorksmobileRow(row: WorksmobileComparisonItem) {
  return row.status === "missing_in_worksmobile" && Boolean(row.baronId);
}

const immutableWorksmobileAccountEmails = new Set([
  "cyhan@samaneng.com",
  "cyhan1@hanmaceng.co.kr",
  "cyhan2@baroncs.co.kr",
  "cyhan3@brsw.kr",
  "su-@samaneng.com",
]);

const hiddenWorksmobileMemberEmails = new Set([
  "su-@samaneng.com",
  "cyhan1@hanmaceng.co.kr",
  "cyhan2@baroncs.co.kr",
  "cyhan3@brsw.kr",
]);

function normalizeWorksmobileEmail(email?: string) {
  return email?.trim().toLowerCase() ?? "";
}

export function isImmutableWorksmobileAccount(row: WorksmobileComparisonItem) {
  return (
    row.resourceType === "USER" &&
    immutableWorksmobileAccountEmails.has(
      normalizeWorksmobileEmail(row.worksmobileEmail),
    )
  );
}

export function isHiddenWorksmobileMember(row: WorksmobileComparisonItem) {
  if (row.resourceType !== "USER") {
    return false;
  }

  return [row.worksmobileEmail, row.baronEmail].some((email) =>
    hiddenWorksmobileMemberEmails.has(normalizeWorksmobileEmail(email)),
  );
}

export function filterVisibleWorksmobileComparisonRows(
  rows: WorksmobileComparisonItem[],
) {
  return rows.filter((row) => !isHiddenWorksmobileMember(row));
}

export function getWorksmobileRowSelectionKey(row: WorksmobileComparisonItem) {
  if (row.baronId) {
    return `${row.resourceType}:baron:${row.baronId}`;
  }
  if (row.worksmobileId) {
    return `${row.resourceType}:works:${row.worksmobileId}`;
  }
  if (row.externalKey) {
    return `${row.resourceType}:external:${row.externalKey}`;
  }
  return "";
}

export function canSelectWorksmobileRow(row: WorksmobileComparisonItem) {
  return (
    Boolean(getWorksmobileRowSelectionKey(row)) &&
    !isImmutableWorksmobileAccount(row)
  );
}

export function getWorksmobileSelectedActionIds(
  rows: WorksmobileComparisonItem[],
  selectedKeys: string[],
) {
  const selected = new Set(selectedKeys);
  return rows
    .filter((row) => selected.has(getWorksmobileRowSelectionKey(row)))
    .map((row) => row.baronId)
    .filter((id): id is string => Boolean(id));
}

export function getWorksmobileSelectedMissingExternalKeyOrgUnitIds(
  rows: WorksmobileComparisonItem[],
  selectedKeys: string[],
) {
  return getWorksmobileSelectedWorksOnlyOrgUnitIds(rows, selectedKeys).filter(
    (id) =>
      rows.some(
        (row) =>
          row.worksmobileId === id && row.status === "missing_external_key",
      ),
  );
}

export function getWorksmobileSelectedWorksOnlyOrgUnitIds(
  rows: WorksmobileComparisonItem[],
  selectedKeys: string[],
) {
  const selected = new Set(selectedKeys);
  return rows
    .filter(
      (row) =>
        row.resourceType === "GROUP" &&
        (row.status === "missing_external_key" ||
          row.status === "missing_in_baron") &&
        selected.has(getWorksmobileRowSelectionKey(row)),
    )
    .map((row) => row.worksmobileId)
    .filter((id): id is string => Boolean(id));
}

const worksmobileComparisonSearchFields: Array<
  keyof WorksmobileComparisonItem
> = [
  "baronId",
  "baronSlug",
  "baronName",
  "baronEmail",
  "baronPrimaryOrgId",
  "baronPrimaryOrgSlug",
  "baronPrimaryOrgName",
  "baronParentId",
  "baronParentSlug",
  "baronParentName",
  "worksmobileId",
  "externalKey",
  "worksmobileName",
  "worksmobileEmail",
  "worksmobileLevelId",
  "worksmobileLevelName",
  "worksmobileTask",
  "worksmobileDomainId",
  "worksmobileDomainName",
  "worksmobilePrimaryOrgId",
  "worksmobilePrimaryOrgName",
  "worksmobilePrimaryOrgPositionId",
  "worksmobilePrimaryOrgPositionName",
  "baronParentWorksmobileId",
  "baronParentWorksmobileName",
  "baronParentWorksmobileEmail",
  "worksmobileParentId",
  "worksmobileParentName",
  "worksmobileParentEmail",
  "worksmobileParentExternalKey",
];

export function filterWorksmobileComparisonRowsBySearch(
  rows: WorksmobileComparisonItem[],
  search: string,
) {
  const keyword = search.trim().toLowerCase();
  if (!keyword) {
    return rows;
  }
  return rows.filter((row) =>
    worksmobileComparisonSearchFields.some((field) => {
      const value = row[field];
      if (value === undefined || value === null) {
        return false;
      }
      return String(value).toLowerCase().includes(keyword);
    }),
  );
}

export function filterWorksmobileComparisonRows(
  rows: WorksmobileComparisonItem[],
  filters: WorksmobileComparisonFilter[],
  onlyMissingExternalKey = false,
) {
  const allowedStatuses = new Set(
    filters.flatMap((filter) => worksmobileFilterStatuses[filter]),
  );
  if (filters.includes("works_only")) {
    if (onlyMissingExternalKey) {
      allowedStatuses.delete("missing_in_baron");
    }
    allowedStatuses.add("missing_external_key");
  }
  return rows.filter((row) => allowedStatuses.has(row.status));
}

export function formatWorksmobilePersonName(row: WorksmobileComparisonItem) {
  return [
    row.worksmobileName,
    row.worksmobileLevelName ?? row.worksmobileLevelId,
  ]
    .filter(Boolean)
    .join(" ");
}

export function formatWorksmobileOrgDetails(row: WorksmobileComparisonItem) {
  const details: string[] = [];
  const position =
    row.worksmobilePrimaryOrgPositionName ??
    row.worksmobilePrimaryOrgPositionId;
  if (position) {
    details.push(`직책 ${position}`);
  }
  if (row.worksmobileTask) {
    details.push(`직무 ${row.worksmobileTask}`);
  }
  if (typeof row.worksmobilePrimaryOrgIsManager === "boolean") {
    details.push(row.worksmobilePrimaryOrgIsManager ? "조직장" : "조직장 아님");
  }
  return details;
}

export function formatWorksmobileUpdateDetails(row: WorksmobileComparisonItem) {
  if (row.status !== "needs_update") {
    return [];
  }

  const details: string[] = [];
  const baronName = row.baronName?.trim();
  const worksmobileName = row.worksmobileName?.trim();
  if (baronName && worksmobileName && baronName !== worksmobileName) {
    details.push(`이름: ${worksmobileName} -> ${baronName}`);
  }

  const expectedParent =
    row.baronParentWorksmobileName ??
    row.baronParentName ??
    row.baronParentWorksmobileId ??
    row.baronParentId ??
    "";
  const actualParent =
    row.worksmobileParentName ??
    row.worksmobileParentExternalKey ??
    row.worksmobileParentId ??
    "";
  const expectedParentKey =
    row.baronParentWorksmobileId ?? row.baronParentId ?? "";
  const actualParentKey =
    row.worksmobileParentId ?? row.worksmobileParentExternalKey ?? "";
  if (expectedParentKey !== actualParentKey) {
    details.push(
      `상위: ${actualParent || "없음"} -> ${expectedParent || "없음"}`,
    );
  }

  return details;
}

export function buildWorksmobilePasswordManageUrl({
  tenantId,
  domainId,
  userIdNo,
}: {
  tenantId?: string;
  domainId?: number;
  userIdNo?: string;
}) {
  const normalizedTenantId = tenantId?.trim();
  const normalizedUserIdNo = userIdNo?.trim();
  if (
    !normalizedTenantId ||
    !domainId ||
    domainId <= 0 ||
    !normalizedUserIdNo
  ) {
    return "";
  }
  const url = new URL("https://auth.worksmobile.com/integrate/password/manage");
  url.searchParams.set("usage", "admin");
  url.searchParams.set("targetUserTenantId", normalizedTenantId);
  url.searchParams.set("targetUserDomainId", String(domainId));
  url.searchParams.set("targetUserIdNo", normalizedUserIdNo);
  url.searchParams.set(
    "accessUrl",
    "https://admin.worksmobile.com/assets/self-close.html",
  );
  return url.toString();
}

export function canOpenWorksmobilePasswordManage(
  row: WorksmobileComparisonItem,
  tenantId?: string,
) {
  return (
    row.resourceType === "USER" &&
    !isImmutableWorksmobileAccount(row) &&
    Boolean(
      buildWorksmobilePasswordManageUrl({
        tenantId,
        domainId: row.worksmobileDomainId,
        userIdNo: row.worksmobileId,
      }),
    )
  );
}

export const comparisonFilterOptions: Array<{
  value: WorksmobileComparisonFilter;
  label: string;
}> = [
  { value: "baron_only", label: "바론에만 있음" },
  { value: "needs_update", label: "업데이트 필요" },
  { value: "works_only", label: "웍스에만 있음" },
  { value: "matched", label: "양쪽 다 있음" },
];

export const userFilterOptions = comparisonFilterOptions;

export function getDefaultGroupComparisonFilters(): WorksmobileComparisonFilter[] {
  return ["baron_only", "needs_update", "works_only"];
}

const worksmobileFilterStatuses: Record<WorksmobileComparisonFilter, string[]> =
  {
    baron_only: ["missing_in_worksmobile"],
    needs_update: ["needs_update"],
    works_only: ["missing_in_baron"],
    matched: ["matched"],
  };
