import { z } from 'zod'
import { OrganizationModelBrandingSchema, DEFAULT_ORGANIZATION_MODEL_BRANDING } from './domains/branding'
import { OrganizationModelNavigationSchema } from './domains/navigation'
import { IdentityDomainSchema, DEFAULT_ORGANIZATION_MODEL_IDENTITY } from './domains/identity'
import { CustomersDomainSchema, DEFAULT_ORGANIZATION_MODEL_CUSTOMERS } from './domains/customers'
import { OfferingsDomainSchema, DEFAULT_ORGANIZATION_MODEL_OFFERINGS } from './domains/offerings'
import { RolesDomainSchema, DEFAULT_ORGANIZATION_MODEL_ROLES } from './domains/roles'
import { GoalsDomainSchema, DEFAULT_ORGANIZATION_MODEL_GOALS } from './domains/goals'
import { KnowledgeDomainSchema } from './domains/knowledge'
import { SystemsDomainSchema, DEFAULT_ORGANIZATION_MODEL_SYSTEMS } from './domains/systems'
import { ResourcesDomainSchema, DEFAULT_ORGANIZATION_MODEL_RESOURCES } from './domains/resources'
import { OmTopologyDomainSchema, DEFAULT_ORGANIZATION_MODEL_TOPOLOGY } from './domains/topology'
import { ActionsDomainSchema, DEFAULT_ORGANIZATION_MODEL_ACTIONS } from './domains/actions'
import { EntitiesDomainSchema } from './domains/entities'
import { PoliciesDomainSchema, DEFAULT_ORGANIZATION_MODEL_POLICIES } from './domains/policies'
import { DEFAULT_ONTOLOGY_SCOPE, OntologyScopeSchema } from './ontology'
import { refineOrganizationModel } from './schema-refinements'
import { JsonValueSchema } from './domains/systems'
import { LabelSchema, ModelIdSchema } from './domains/shared'

export const ClientProfileIdSchema = z.string().uuid()
export const ClientProfileStatusSchema = z.enum(['active', 'onboarding', 'paused', 'completed', 'churned'])
export const ClientProfileSourceSchema = z
  .string()
  .trim()
  .min(1)
  .max(64)
  .regex(/^[a-z][a-z0-9_]*$/, 'Source must use lowercase letters, numbers, and underscores')

export const ClientProfileIdentitySchema = z
  .object({
    organizationName: LabelSchema.optional(),
    shortName: z.string().trim().min(1).max(40).optional(),
    clientBrief: z.string().trim().max(4000).default(''),
    geographicFocus: z.array(z.string().trim().min(1).max(200)).default([]),
    timeZone: z.string().trim().min(1).max(100).default('UTC')
  })
  .passthrough()
  .default({
    clientBrief: '',
    geographicFocus: [],
    timeZone: 'UTC'
  })

export const ClientProfileBrandingSchema = z
  .object({
    voice: z.string().trim().max(280).optional(),
    tagline: z.string().trim().max(200).optional(),
    values: z.array(z.string().trim().min(1).max(100)).default([])
  })
  .passthrough()
  .default({
    values: []
  })

export const ClientProfileWorkspaceSchema = z
  .object({
    kind: z.enum(['external-project', 'internal-project', 'none']).optional(),
    owner: z.enum(['developer', 'client', 'platform']).optional(),
    projectId: z.string().trim().min(1).max(200).optional(),
    workspacePath: z.string().trim().min(1).max(500).optional()
  })
  .passthrough()
  .default({})

export const ClientProfileLinksSchema = z
  .object({
    projectIds: z.array(z.string().uuid()).default([]),
    primaryCompanyId: z.string().uuid().optional(),
    primaryContactId: z.string().uuid().optional(),
    sourceDealId: z.string().uuid().optional()
  })
  .default({
    projectIds: []
  })

export const ClientProfilePromptsSchema = z
  .object({
    defaultContext: z.string().trim().max(8000).default('')
  })
  .passthrough()
  .default({
    defaultContext: ''
  })

export const ClientProfileSchema = z
  .object({
    id: ClientProfileIdSchema,
    slug: ModelIdSchema,
    name: LabelSchema,
    status: ClientProfileStatusSchema.default('onboarding'),
    source: ClientProfileSourceSchema.optional(),
    identity: ClientProfileIdentitySchema,
    branding: ClientProfileBrandingSchema,
    workspace: ClientProfileWorkspaceSchema,
    links: ClientProfileLinksSchema,
    prompts: ClientProfilePromptsSchema,
    config: z.record(z.string().trim().min(1).max(200), JsonValueSchema).default({}),
    customValues: z.record(z.string().trim().min(1).max(200), JsonValueSchema).default({})
  })
  .strict()

export const ClientProfilesDomainSchema = z
  .record(ClientProfileIdSchema, ClientProfileSchema)
  .refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
    message: 'Each client profile id must match its map key'
  })
  .default({})

export const DEFAULT_ORGANIZATION_MODEL_CLIENTS: z.infer<typeof ClientProfilesDomainSchema> = {}

// Phase 4 cut: 'sales', 'prospecting', 'projects', 'statuses' removed.
// domainMetadata.knowledge covers versioning for the knowledge flat-map (D7).
export const OrganizationModelDomainKeySchema = z.enum([
  'branding',
  'identity',
  'clients',
  'customers',
  'offerings',
  'roles',
  'goals',
  'systems',
  'ontology',
  'resources',
  'topology',
  'actions',
  'entities',
  'policies',
  'knowledge'
])

export const OrganizationModelDomainMetadataSchema = z.object({
  version: z.literal(1).default(1),
  lastModified: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'lastModified must be an ISO date string (YYYY-MM-DD)')
})

export const DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA: Record<
  z.infer<typeof OrganizationModelDomainKeySchema>,
  z.infer<typeof OrganizationModelDomainMetadataSchema>
> = {
  branding: { version: 1, lastModified: '2026-05-10' },
  identity: { version: 1, lastModified: '2026-05-10' },
  clients: { version: 1, lastModified: '2026-05-30' },
  customers: { version: 1, lastModified: '2026-05-10' },
  offerings: { version: 1, lastModified: '2026-05-10' },
  roles: { version: 1, lastModified: '2026-05-10' },
  goals: { version: 1, lastModified: '2026-05-10' },
  systems: { version: 1, lastModified: '2026-05-10' },
  ontology: { version: 1, lastModified: '2026-05-14' },
  resources: { version: 1, lastModified: '2026-05-10' },
  topology: { version: 1, lastModified: '2026-05-14' },
  actions: { version: 1, lastModified: '2026-05-10' },
  entities: { version: 1, lastModified: '2026-05-10' },
  policies: { version: 1, lastModified: '2026-05-10' },
  knowledge: { version: 1, lastModified: '2026-05-10' }
}

export const OrganizationModelDomainMetadataByDomainSchema = z
  .object({
    branding: OrganizationModelDomainMetadataSchema,
    identity: OrganizationModelDomainMetadataSchema,
    clients: OrganizationModelDomainMetadataSchema,
    customers: OrganizationModelDomainMetadataSchema,
    offerings: OrganizationModelDomainMetadataSchema,
    roles: OrganizationModelDomainMetadataSchema,
    goals: OrganizationModelDomainMetadataSchema,
    systems: OrganizationModelDomainMetadataSchema,
    ontology: OrganizationModelDomainMetadataSchema,
    resources: OrganizationModelDomainMetadataSchema,
    topology: OrganizationModelDomainMetadataSchema,
    actions: OrganizationModelDomainMetadataSchema,
    entities: OrganizationModelDomainMetadataSchema,
    policies: OrganizationModelDomainMetadataSchema,
    knowledge: OrganizationModelDomainMetadataSchema
  })
  .partial()
  .default(DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA)
  .transform((metadata) => ({ ...DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA, ...metadata }))

// Phase 4 schema cut (D8):
//   REMOVED top-level fields: sales, prospecting, projects, statuses
//   ADDED navigation.sidebar as the authored shell tree
//   knowledge: now Record<id, OrgKnowledgeNode> flat map (D3); version/lastModified in domainMetadata.knowledge (D7)
//
// Clean migration rule:
//   NO top-level surfaces / navigationGroups compatibility fields.
//   Surfaces are derived from navigation.sidebar routeable leaves.
const OrganizationModelSchemaBase = z.object({
  version: z.literal(1).default(1),
  /**
   * Deterministic SHA-256 hex hash of the full resolved model, excluding this
   * field itself and volatile domainMetadata.lastModified values.
   *
   * Stamped at deploy time by the platform OM assembly and persisted alongside
   * the snapshot in the DB. Compared at API boot to detect stale deployed
   * snapshots (primary gate: deploy; secondary backstop: boot).
   *
   * Optional — absent on models that predate Step 2 versioning or that have
   * not been stamped (e.g. tenant partial overrides before re-deploy).
   */
  snapshotHash: z.string().optional(),
  domainMetadata: OrganizationModelDomainMetadataByDomainSchema,
  branding: OrganizationModelBrandingSchema.default(DEFAULT_ORGANIZATION_MODEL_BRANDING),
  navigation: OrganizationModelNavigationSchema,
  identity: IdentityDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_IDENTITY),
  clients: ClientProfilesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_CLIENTS),
  customers: CustomersDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_CUSTOMERS),
  offerings: OfferingsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_OFFERINGS),
  roles: RolesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ROLES),
  goals: GoalsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_GOALS),
  systems: SystemsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_SYSTEMS),
  ontology: OntologyScopeSchema.default(DEFAULT_ONTOLOGY_SCOPE),
  resources: ResourcesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_RESOURCES),
  topology: OmTopologyDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_TOPOLOGY),
  actions: ActionsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ACTIONS),
  entities: EntitiesDomainSchema.default({}),
  policies: PoliciesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_POLICIES),
  // D3: flat Record<id, OrgKnowledgeNode> — no wrapper object
  knowledge: KnowledgeDomainSchema.default({})
})

export const OrganizationModelSchema = OrganizationModelSchemaBase.superRefine(refineOrganizationModel)
