ALTER TABLE base_model_catalog
  ADD COLUMN IF NOT EXISTS invocation_name text;

UPDATE base_model_catalog
SET invocation_name = COALESCE(
      NULLIF(metadata->>'officialModelId', ''),
      NULLIF(provider_model_name, ''),
      canonical_model_key
    )
WHERE invocation_name IS NULL OR trim(invocation_name) = '';

UPDATE base_model_catalog
SET display_name = COALESCE(
      NULLIF(metadata->>'officialDisplayName', ''),
      NULLIF(default_snapshot->>'displayName', ''),
      NULLIF(display_name, ''),
      invocation_name
    )
WHERE catalog_type = 'system';

ALTER TABLE base_model_catalog
  ALTER COLUMN invocation_name SET NOT NULL;

CREATE INDEX IF NOT EXISTS idx_base_model_catalog_invocation_name
  ON base_model_catalog(invocation_name);

CREATE TABLE IF NOT EXISTS model_compatibility_aliases (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  base_model_id uuid NOT NULL REFERENCES base_model_catalog(id) ON DELETE CASCADE,
  alias text NOT NULL,
  model_type text NOT NULL,
  active boolean NOT NULL DEFAULT true,
  expires_at timestamptz,
  created_at timestamptz NOT NULL DEFAULT now(),
  updated_at timestamptz NOT NULL DEFAULT now(),
  CONSTRAINT model_compatibility_aliases_nonempty CHECK (trim(alias) <> ''),
  CONSTRAINT model_compatibility_aliases_unique UNIQUE (base_model_id, alias, model_type)
);

CREATE INDEX IF NOT EXISTS idx_model_compatibility_aliases_lookup
  ON model_compatibility_aliases(alias, model_type)
  WHERE active = true;

CREATE TABLE IF NOT EXISTS model_alias_usage_metrics (
  alias text NOT NULL,
  canonical_model_key text NOT NULL,
  model_type text NOT NULL,
  hit_count bigint NOT NULL DEFAULT 0,
  first_used_at timestamptz NOT NULL DEFAULT now(),
  last_used_at timestamptz NOT NULL DEFAULT now(),
  PRIMARY KEY (alias, canonical_model_key, model_type)
);

-- Preserve unambiguous historical card/call names for the 14-day compatibility
-- window. Ambiguous names are deliberately not inferred: they must be resolved
-- to one canonical identity by an administrator before they can be registered.
WITH alias_candidates AS (
  SELECT b.id AS base_model_id,
         old_name.alias,
         model_type.value AS model_type,
         b.invocation_name
  FROM base_model_catalog b
  CROSS JOIN LATERAL jsonb_array_elements_text(b.model_type) AS model_type(value)
  CROSS JOIN LATERAL (
    SELECT b.display_name AS alias
    UNION
    SELECT b.canonical_model_key AS alias
  ) old_name
  WHERE trim(COALESCE(old_name.alias, '')) <> ''
    AND old_name.alias <> b.invocation_name
), unambiguous AS (
  SELECT alias, model_type, min(base_model_id::text)::uuid AS base_model_id
  FROM alias_candidates
  GROUP BY alias, model_type
  HAVING count(DISTINCT invocation_name) = 1
)
INSERT INTO model_compatibility_aliases (base_model_id, alias, model_type, expires_at)
SELECT base_model_id, alias, model_type, now() + interval '14 days'
FROM unambiguous
ON CONFLICT (base_model_id, alias, model_type) DO NOTHING;

-- Keep the old platform model_name/model_alias values as explicit compatibility
-- aliases before canonical invocation names are written to platform_models.
WITH platform_alias_candidates AS (
  SELECT b.id AS base_model_id,
         old_name.alias,
         model_type.value AS model_type,
         b.invocation_name
  FROM platform_models pm
  JOIN base_model_catalog b ON b.id = pm.base_model_id
  CROSS JOIN LATERAL jsonb_array_elements_text(pm.model_type) AS model_type(value)
  CROSS JOIN LATERAL (
    SELECT pm.model_name AS alias
    UNION
    SELECT pm.model_alias AS alias
  ) old_name
  WHERE trim(COALESCE(old_name.alias, '')) <> ''
    AND old_name.alias <> b.invocation_name
), unambiguous AS (
  SELECT alias, model_type, min(base_model_id::text)::uuid AS base_model_id
  FROM platform_alias_candidates
  GROUP BY alias, model_type
  HAVING count(DISTINCT invocation_name) = 1
)
INSERT INTO model_compatibility_aliases (base_model_id, alias, model_type, expires_at)
SELECT base_model_id, alias, model_type, now() + interval '14 days'
FROM unambiguous
ON CONFLICT (base_model_id, alias, model_type) DO NOTHING;

WITH ranked_targets AS (
  SELECT pm.id,
         b.invocation_name,
         COALESCE(NULLIF(b.display_name, ''), b.invocation_name) AS display_name,
         row_number() OVER (
           PARTITION BY pm.platform_id, b.invocation_name
           ORDER BY CASE WHEN pm.model_name = b.invocation_name THEN 0 ELSE 1 END,
                    pm.created_at ASC,
                    pm.id ASC
         ) AS identity_rank
  FROM platform_models pm
  JOIN base_model_catalog b ON b.id = pm.base_model_id
)
UPDATE platform_models pm
SET model_name = target.invocation_name,
    model_alias = target.invocation_name,
    display_name = target.display_name,
    updated_at = now()
FROM ranked_targets target
WHERE target.id = pm.id
  AND target.identity_rank = 1
  AND NOT EXISTS (
    SELECT 1
    FROM platform_models conflict
    WHERE conflict.platform_id = pm.platform_id
      AND conflict.id <> pm.id
      AND conflict.model_name = target.invocation_name
  );

UPDATE base_model_catalog
SET default_snapshot = default_snapshot || jsonb_build_object(
      'invocationName', invocation_name,
      'modelAlias', invocation_name,
      'displayName', display_name
    )
WHERE catalog_type = 'system'
  AND COALESCE(default_snapshot, '{}'::jsonb) <> '{}'::jsonb;

CREATE OR REPLACE FUNCTION fill_system_base_model_default_snapshot()
RETURNS trigger AS $$
BEGIN
  IF NEW.catalog_type = 'system' AND NEW.default_snapshot IS NULL THEN
    NEW.default_snapshot = jsonb_build_object(
      'providerKey', NEW.provider_key,
      'canonicalModelKey', NEW.canonical_model_key,
      'invocationName', NEW.invocation_name,
      'providerModelName', NEW.provider_model_name,
      'modelType', NEW.model_type,
      'modelAlias', NEW.invocation_name,
      'displayName', NEW.display_name,
      'capabilities', NEW.capabilities,
      'baseBillingConfig', NEW.base_billing_config,
      'defaultRateLimitPolicy', NEW.default_rate_limit_policy,
      'pricingRuleSetId', COALESCE(NEW.pricing_rule_set_id::text, ''),
      'runtimePolicySetId', COALESCE(NEW.runtime_policy_set_id::text, ''),
      'runtimePolicyOverride', NEW.runtime_policy_override,
      'metadata', NEW.metadata,
      'pricingVersion', NEW.pricing_version,
      'status', NEW.status
    );
  END IF;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;
