import type { ApiOrgPolicy, ApiOrgSettingsResponse } from "@/lib/api/admin-org-types"
import type { OrgPolicySectionKey } from "@/lib/api/admin-org-types"
import { DEFAULT_ULTIAI_ENABLED_TOOLS } from "@/lib/ai/ultiai-tool-groups"
import type { IntegrationEntry, OrgSettingsState, FilePolicySettings, DriveMountOAuthSettings, DriveMountOAuthProviderSettings, IdentityProvidersPolicy, IdentityProvider, PluginEntry } from "@/lib/admin-settings/org-settings-types"
import { DEFAULT_ORG_PLUGINS } from "@/lib/admin-settings/default-plugins"
import { DEFAULT_MEET_POLICY } from "@/lib/meet/meet-settings-types"
import { normalizeLlmProvider } from "@/lib/llm/llm-provider-catalog"

const INTEGRATION_HREFS: Record<string, string> = {
  authentik: "/admin/settings/authentication",
  nextcloud: "/admin/settings/plugins",
  onlyoffice: "/admin/settings/plugins",
  smtp: "/admin/settings/mail-domains",
}

function mergePlugins(fromApi: PluginEntry[] | undefined): PluginEntry[] {
  if (!fromApi?.length) return DEFAULT_ORG_PLUGINS.map((plugin) => ({ ...plugin }))
  const byId = new Map(fromApi.map((plugin) => [plugin.id, plugin]))
  const merged = DEFAULT_ORG_PLUGINS.map((plugin) => ({
    ...plugin,
    ...byId.get(plugin.id),
  }))
  for (const plugin of fromApi) {
    if (!DEFAULT_ORG_PLUGINS.some((entry) => entry.id === plugin.id)) {
      merged.push(plugin)
    }
  }
  return merged
}

function mergeIntegrations(
  fromApi: IntegrationEntry[] | undefined
): IntegrationEntry[] {
  if (!fromApi?.length) return []
  return fromApi.map((item) => ({
    ...item,
    href: INTEGRATION_HREFS[item.id] ?? item.href,
  }))
}

const DEFAULT_IDENTITY_PROVIDERS: IdentityProvidersPolicy = {
  allow_self_enrollment: true,
  default_login_source: "",
  providers: [],
}

function mergeIdentityProviders(
  fromApi: Partial<IdentityProvidersPolicy> | undefined
): IdentityProvidersPolicy {
  return {
    ...DEFAULT_IDENTITY_PROVIDERS,
    ...fromApi,
    providers: (fromApi?.providers ?? []).map((provider) => ({
      ...provider,
      allowed_email_domains: provider.allowed_email_domains ?? [],
      allowed_identities: provider.allowed_identities ?? [],
      allowed_organizations: provider.allowed_organizations ?? [],
      default_groups: provider.default_groups ?? [],
      sync_status: provider.sync_status ?? "pending",
      oauth: provider.oauth
        ? { ...provider.oauth, client_secret: provider.oauth.client_secret ?? "" }
        : undefined,
      ldap: provider.ldap
        ? { ...provider.ldap, bind_password: provider.ldap.bind_password ?? "" }
        : undefined,
      saml: provider.saml
        ? { ...provider.saml, signing_cert: provider.saml.signing_cert ?? "" }
        : undefined,
    })),
  }
}

function mapProviderToApi(provider: IdentityProvider) {
  return {
    id: provider.id,
    name: provider.name,
    slug: provider.slug,
    type: provider.type,
    enabled: provider.enabled,
    authentik_pk: provider.authentik_pk,
    sync_status: provider.sync_status,
    sync_error: provider.sync_error,
    last_synced_at: provider.last_synced_at,
    allowed_email_domains: provider.allowed_email_domains,
    allowed_identities: provider.allowed_identities,
    allowed_organizations: provider.allowed_organizations,
    default_groups: provider.default_groups,
    oauth: provider.oauth,
    saml: provider.saml,
    ldap: provider.ldap,
  }
}

const DEFAULT_MOUNT_OAUTH_PROVIDER: DriveMountOAuthProviderSettings = {
  enabled: false,
  client_id: "",
  client_secret: "",
}

const DEFAULT_MOUNT_OAUTH: DriveMountOAuthSettings = {
  redirect_uri: "",
  google: { ...DEFAULT_MOUNT_OAUTH_PROVIDER },
  dropbox: { ...DEFAULT_MOUNT_OAUTH_PROVIDER },
  microsoft: { ...DEFAULT_MOUNT_OAUTH_PROVIDER },
}

const DEFAULT_FILE_POLICIES: FilePolicySettings = {
  max_upload_mib: 512,
  allowed_extensions: "",
  block_executable: true,
  external_sharing: "authenticated",
  default_link_expiry_days: 30,
  virus_scan_enabled: false,
  virustotal_api_key: "",
  retention_trash_days: 30,
  mount_oauth: DEFAULT_MOUNT_OAUTH,
}

function mergeFilePolicies(fromApi: Partial<FilePolicySettings> | undefined): FilePolicySettings {
  const mountOAuth = fromApi?.mount_oauth
  return {
    ...DEFAULT_FILE_POLICIES,
    ...fromApi,
    virustotal_api_key: fromApi?.virustotal_api_key ?? "",
    mount_oauth: {
      ...DEFAULT_MOUNT_OAUTH,
      ...mountOAuth,
      google: { ...DEFAULT_MOUNT_OAUTH.google, ...mountOAuth?.google, client_secret: mountOAuth?.google?.client_secret ?? "" },
      dropbox: { ...DEFAULT_MOUNT_OAUTH.dropbox, ...mountOAuth?.dropbox, client_secret: mountOAuth?.dropbox?.client_secret ?? "" },
      microsoft: { ...DEFAULT_MOUNT_OAUTH.microsoft, ...mountOAuth?.microsoft, client_secret: mountOAuth?.microsoft?.client_secret ?? "" },
    },
  }
}

export function apiOrgPolicyToStore(policy: ApiOrgPolicy): Partial<OrgSettingsState> {
  return {
    authentik: {
      enabled: policy.authentik.enabled,
      api_url: policy.authentik.api_url,
      slug: policy.authentik.slug,
      client_id: policy.authentik.client_id,
      enforce_sso: policy.authentik.enforce_sso,
      allow_password_fallback: policy.authentik.allow_password_fallback,
      default_groups: policy.authentik.default_groups,
    },
    identityProviders: mergeIdentityProviders(policy.identity_providers),
    twoFactor: {
      required_for_all: policy.two_factor.required_for_all,
      required_for_admins: policy.two_factor.required_for_admins,
      allowed_methods: policy.two_factor.allowed_methods.filter(
        (m): m is "totp" | "webauthn" => m === "totp" || m === "webauthn"
      ),
      grace_period_days: policy.two_factor.grace_period_days,
      remember_device_days: policy.two_factor.remember_device_days,
    },
    storageQuotas: { ...policy.storage_quotas },
    usageQuotas: { ...policy.usage_quotas },
    filePolicies: mergeFilePolicies(policy.file_policies),
    llm: {
      ...policy.llm,
      providers: (policy.llm.providers ?? []).map((provider) =>
        normalizeLlmProvider({
          ...provider,
          api_key: provider.api_key ?? "",
        }),
      ),
    },
    search: {
      ...policy.search,
      web_search: policy.search.web_search ?? {
        default_provider_id: "brave-default",
        providers: [],
      },
    },
    administrators: policy.administrators ?? [],
    nextcloud: { ...policy.nextcloud },
    mailing: { ...policy.mailing },
    onlyoffice: { ...policy.onlyoffice },
    richtext: {
      enabled: policy.richtext?.enabled ?? true,
      storage_mode: policy.richtext?.storage_mode ?? "sidecar",
      export_mirror_format: policy.richtext?.export_mirror_format ?? "",
      hocuspocus_url: policy.richtext?.hocuspocus_url ?? "",
    },
    aiAssistant: {
      enabled: policy.ai_assistant?.enabled ?? false,
      openwebui_internal_url: policy.ai_assistant?.openwebui_internal_url ?? "",
      public_path: policy.ai_assistant?.public_path ?? "/ai",
      embed_default_temporary: policy.ai_assistant?.embed_default_temporary ?? false,
      default_model: policy.ai_assistant?.default_model ?? "",
      enabled_tools: policy.ai_assistant?.enabled_tools ?? [...DEFAULT_ULTIAI_ENABLED_TOOLS],
      chat_sync_enabled: policy.ai_assistant?.chat_sync_enabled ?? true,
      chat_nc_path: policy.ai_assistant?.chat_nc_path ?? "/.ultimail/ai/chats",
      models: (policy.ai_assistant?.models ?? []).map((entry) => ({
        model_id: entry.model_id ?? "",
        label: entry.label ?? "",
        enabled: entry.enabled ?? true,
      })),
    },
    agenda: {
      default_theme_mode: policy.agenda?.default_theme_mode ?? "system",
      enforce_org_theme: policy.agenda?.enforce_org_theme ?? false,
      default_video_provider: policy.agenda?.default_video_provider ?? "ultimeet",
      enforce_org_video_provider: policy.agenda?.enforce_org_video_provider ?? false,
      video_provider_api_keys: policy.agenda?.video_provider_api_keys ?? {},
    },
    meet: {
      ...DEFAULT_MEET_POLICY,
      ...policy.meet,
      post_actions: {
        ...DEFAULT_MEET_POLICY.post_actions,
        ...policy.meet?.post_actions,
      },
    },
    plugins: mergePlugins(policy.plugins),
    integrations: mergeIntegrations(policy.integrations as IntegrationEntry[]),
  }
}

export function storeToApiOrgPolicy(state: OrgSettingsState): ApiOrgPolicy {
  return {
    authentik: {
      enabled: state.authentik.enabled,
      api_url: state.authentik.api_url,
      slug: state.authentik.slug,
      client_id: state.authentik.client_id,
      enforce_sso: state.authentik.enforce_sso,
      allow_password_fallback: state.authentik.allow_password_fallback,
      default_groups: state.authentik.default_groups,
    },
    identity_providers: {
      allow_self_enrollment: state.identityProviders.allow_self_enrollment,
      default_login_source: state.identityProviders.default_login_source,
      providers: state.identityProviders.providers.map(mapProviderToApi),
    },
    two_factor: {
      required_for_all: state.twoFactor.required_for_all,
      required_for_admins: state.twoFactor.required_for_admins,
      allowed_methods: state.twoFactor.allowed_methods.filter(
        (m): m is "totp" | "webauthn" => m === "totp" || m === "webauthn"
      ),
      grace_period_days: state.twoFactor.grace_period_days,
      remember_device_days: state.twoFactor.remember_device_days,
    },
    storage_quotas: { ...state.storageQuotas },
    usage_quotas: { ...state.usageQuotas },
    file_policies: { ...state.filePolicies },
    llm: {
      default_provider_id: state.llm.default_provider_id,
      providers: state.llm.providers,
      contact_discovery_model: state.llm.contact_discovery_model,
      contact_discovery_provider_id: state.llm.contact_discovery_provider_id,
      enforce_org_providers: state.llm.enforce_org_providers,
      allow_user_override: state.llm.allow_user_override,
    },
    search: {
      suite_engine: state.search.suite_engine,
      meilisearch_url: state.search.meilisearch_url,
      meilisearch_api_key: state.search.meilisearch_api_key,
      typesense_url: state.search.typesense_url,
      typesense_api_key: state.search.typesense_api_key,
      web_search: state.search.web_search,
      enforce_org_search: state.search.enforce_org_search,
    },
    administrators: state.administrators,
    nextcloud: { ...state.nextcloud },
    mailing: { ...state.mailing },
    onlyoffice: { ...state.onlyoffice },
    richtext: { ...state.richtext },
    ai_assistant: { ...state.aiAssistant },
    agenda: { ...state.agenda },
    meet: { ...state.meet },
    plugins: state.plugins.map(({ id, name, description, enabled, version }) => ({
      id,
      name,
      description,
      enabled,
      version,
    })),
    integrations: state.integrations.map(({ id, name, description, enabled, configured }) => ({
      id,
      name,
      description,
      enabled,
      configured,
    })),
  }
}

export function pickApiOrgPolicySections(
  state: OrgSettingsState,
  sections: OrgPolicySectionKey[]
): Partial<ApiOrgPolicy> {
  const full = storeToApiOrgPolicy(state)
  const patch: Partial<ApiOrgPolicy> = {}
  for (const key of sections) {
    patch[key] = full[key] as never
  }
  return patch
}

export type OrgSettingsMeta = {
  effective: ApiOrgSettingsResponse["effective"]
  secrets: ApiOrgSettingsResponse["secrets"]
  envVars: ApiOrgSettingsResponse["env_vars"]
  deployLocked: ApiOrgSettingsResponse["deploy_locked"]
  updatedAt: string
  updatedBy: string
}

export function apiOrgSettingsMeta(data: ApiOrgSettingsResponse): OrgSettingsMeta {
  return {
    effective: data.effective,
    secrets: data.secrets,
    envVars: data.env_vars ?? [],
    deployLocked: data.deploy_locked ?? {},
    updatedAt: data.updated_at,
    updatedBy: data.updated_by,
  }
}
