-- 066_jurisdictions_and_foreign_qual.sql
--
-- Multi-jurisdiction expansion + foreign qualification support.
--
-- Context:
--   Migration 002 seeded `state_filing_fees` with 50 US states + DC and
--   created `formation_orders` constrained to US entity types. BC has
--   been bolted on for CRTC work, but there's no unified jurisdiction
--   model and no way to order a Certificate of Authority in one or
--   more states from a formation-only OR FCC multi-state client.
--
-- This migration:
--
-- 1. Creates a unified `jurisdictions` table (all US states + DC + CA
--    provinces) with country, currency, portal URLs, and a canonical
--    entity-type catalog per jurisdiction. Acts as the single source of
--    truth read by the Python JurisdictionConfig abstraction.
-- 2. Expands `formation_orders` to accept Canadian entity types + a
--    `country` column, without breaking existing US orders.
-- 3. Adds `province` to `canada_crtc_orders` (defaulting to 'BC' for
--    all existing rows so the BC pipeline keeps working).
-- 4. Creates `foreign_qualification_registrations` tracking every
--    Certificate of Authority / Foreign Qualification filing, with a
--    lifecycle independent of formation orders (so FCC clients can
--    order bulk state registration against an already-formed entity).
-- 5. Adds convenience views for the admin dashboard.

BEGIN;

-- ──────────────────────────────────────────────────────────────────────
-- 1. Canonical jurisdiction registry
-- ──────────────────────────────────────────────────────────────────────

CREATE TABLE IF NOT EXISTS jurisdictions (
    code              CHAR(2) PRIMARY KEY,        -- e.g. 'WY', 'BC', 'ON', 'DC'
    name              TEXT NOT NULL,              -- 'Wyoming', 'British Columbia'
    country           CHAR(2) NOT NULL CHECK (country IN ('US', 'CA')),
    kind              TEXT NOT NULL CHECK (kind IN ('state', 'district', 'province', 'territory')),
    currency          CHAR(3) NOT NULL DEFAULT 'USD' CHECK (currency IN ('USD', 'CAD')),
    timezone          TEXT,                        -- 'America/Chicago' etc.

    -- Portal info for formation + foreign qualification
    portal_name       TEXT,                        -- 'WYBiz', 'COLIN', 'OBR'
    portal_url        TEXT,
    portal_login_required BOOLEAN NOT NULL DEFAULT FALSE,

    -- Entity type catalog the jurisdiction recognizes — used by the
    -- intake wizard to present the right options.
    entity_types_json JSONB NOT NULL DEFAULT '[]'::jsonb,
      -- e.g. [{"code":"llc","label":"LLC"},{"code":"corp","label":"Corporation"}]
      --      [{"code":"ltd","label":"Limited Company"},{"code":"inc","label":"Incorporated"}]

    -- Whether we support foreign qualification filings into this
    -- jurisdiction.  Independent of whether we can *form* here.
    supports_foreign_qualification BOOLEAN NOT NULL DEFAULT TRUE,
    foreign_qual_portal_url        TEXT,           -- often different endpoint
    foreign_qual_requires_coa      BOOLEAN NOT NULL DEFAULT TRUE,
      -- Whether the jurisdiction requires a Certificate of Good Standing
      -- from the home state to accompany the foreign qualification.

    -- NW Registered Agent wholesale pricing (integer cents)
    nwra_foreign_qual_wholesale_cents INTEGER,

    -- Ops notes + audit
    notes             TEXT,
    last_verified     DATE DEFAULT CURRENT_DATE,
    created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_jurisdictions_country ON jurisdictions(country);
CREATE INDEX IF NOT EXISTS idx_jurisdictions_kind ON jurisdictions(kind);

-- Seed US states + DC.  Entity-type catalog is the same everywhere in
-- the US (LLC, C-corp, S-corp, Nonprofit, LP/LLP) — jurisdictions that
-- diverge (e.g., closely-held corp, professional corp) can override via
-- update post-seed.
INSERT INTO jurisdictions (code, name, country, kind, currency, timezone, entity_types_json, supports_foreign_qualification)
VALUES
  ('AL','Alabama',       'US','state','USD','America/Chicago',    '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('AK','Alaska',        'US','state','USD','America/Anchorage',  '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('AZ','Arizona',       'US','state','USD','America/Phoenix',    '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('AR','Arkansas',      'US','state','USD','America/Chicago',    '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('CA','California',    'US','state','USD','America/Los_Angeles','[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('CO','Colorado',      'US','state','USD','America/Denver',     '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('CT','Connecticut',   'US','state','USD','America/New_York',   '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('DE','Delaware',      'US','state','USD','America/New_York',   '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('FL','Florida',       'US','state','USD','America/New_York',   '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('GA','Georgia',       'US','state','USD','America/New_York',   '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('HI','Hawaii',        'US','state','USD','Pacific/Honolulu',   '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('ID','Idaho',         'US','state','USD','America/Boise',      '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('IL','Illinois',      'US','state','USD','America/Chicago',    '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('IN','Indiana',       'US','state','USD','America/Indianapolis','[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('IA','Iowa',          'US','state','USD','America/Chicago',    '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('KS','Kansas',        'US','state','USD','America/Chicago',    '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('KY','Kentucky',      'US','state','USD','America/New_York',   '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('LA','Louisiana',     'US','state','USD','America/Chicago',    '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('ME','Maine',         'US','state','USD','America/New_York',   '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('MD','Maryland',      'US','state','USD','America/New_York',   '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('MA','Massachusetts', 'US','state','USD','America/New_York',   '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('MI','Michigan',      'US','state','USD','America/Detroit',    '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('MN','Minnesota',     'US','state','USD','America/Chicago',    '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('MS','Mississippi',   'US','state','USD','America/Chicago',    '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('MO','Missouri',      'US','state','USD','America/Chicago',    '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('MT','Montana',       'US','state','USD','America/Denver',     '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('NE','Nebraska',      'US','state','USD','America/Chicago',    '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('NV','Nevada',        'US','state','USD','America/Los_Angeles','[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('NH','New Hampshire', 'US','state','USD','America/New_York',   '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('NJ','New Jersey',    'US','state','USD','America/New_York',   '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('NM','New Mexico',    'US','state','USD','America/Denver',     '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('NY','New York',      'US','state','USD','America/New_York',   '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('NC','North Carolina','US','state','USD','America/New_York',   '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('ND','North Dakota',  'US','state','USD','America/Chicago',    '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('OH','Ohio',          'US','state','USD','America/New_York',   '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('OK','Oklahoma',      'US','state','USD','America/Chicago',    '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('OR','Oregon',        'US','state','USD','America/Los_Angeles','[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('PA','Pennsylvania',  'US','state','USD','America/New_York',   '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('RI','Rhode Island',  'US','state','USD','America/New_York',   '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('SC','South Carolina','US','state','USD','America/New_York',   '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('SD','South Dakota',  'US','state','USD','America/Chicago',    '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('TN','Tennessee',     'US','state','USD','America/Chicago',    '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('TX','Texas',         'US','state','USD','America/Chicago',    '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('UT','Utah',          'US','state','USD','America/Denver',     '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('VT','Vermont',       'US','state','USD','America/New_York',   '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('VA','Virginia',      'US','state','USD','America/New_York',   '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('WA','Washington',    'US','state','USD','America/Los_Angeles','[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('WV','West Virginia', 'US','state','USD','America/New_York',   '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('WI','Wisconsin',     'US','state','USD','America/Chicago',    '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('WY','Wyoming',       'US','state','USD','America/Denver',     '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  ('DC','District of Columbia','US','district','USD','America/New_York','[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
  -- Canadian provinces: entity_types differ (ltd/inc/corp, sole prop, cooperative)
  ('BC','British Columbia','CA','province','CAD','America/Vancouver','[{"code":"ltd","label":"Limited Company (Ltd.)"},{"code":"inc","label":"Incorporated (Inc.)"},{"code":"corp","label":"Corporation (Corp.)"}]'::jsonb, TRUE),
  ('ON','Ontario',         'CA','province','CAD','America/Toronto',  '[{"code":"ltd","label":"Limited Company (Ltd.)"},{"code":"inc","label":"Incorporated (Inc.)"},{"code":"corp","label":"Corporation (Corp.)"}]'::jsonb, TRUE),
  ('AB','Alberta',         'CA','province','CAD','America/Edmonton', '[{"code":"ltd","label":"Limited Company (Ltd.)"},{"code":"inc","label":"Incorporated (Inc.)"},{"code":"corp","label":"Corporation (Corp.)"}]'::jsonb, FALSE),
  ('QC','Quebec',          'CA','province','CAD','America/Montreal', '[{"code":"inc","label":"Incorporated (Inc.)"}]'::jsonb, FALSE)
ON CONFLICT (code) DO NOTHING;

-- Populate portal fields from state_filing_fees where available.  This
-- keeps the two tables in sync without forcing a second seed pass.
UPDATE jurisdictions j
   SET portal_name = f.portal_name,
       portal_url  = f.portal_url
  FROM state_filing_fees f
 WHERE j.code = f.state_code
   AND j.portal_name IS NULL;

-- ──────────────────────────────────────────────────────────────────────
-- 2. formation_orders: expand entity_type + add country
-- ──────────────────────────────────────────────────────────────────────

ALTER TABLE formation_orders
  ADD COLUMN IF NOT EXISTS country CHAR(2) NOT NULL DEFAULT 'US'
    CHECK (country IN ('US', 'CA'));

-- Drop the old entity_type CHECK (which limited us to LLC/corp/s_corp)
-- and replace with one that allows Canadian types.  Keep the data — no
-- rewrites.
ALTER TABLE formation_orders
  DROP CONSTRAINT IF EXISTS formation_orders_entity_type_check;

ALTER TABLE formation_orders
  ADD CONSTRAINT formation_orders_entity_type_check
  CHECK (entity_type IN (
    'llc', 'corporation', 's_corp', 'c_corp', 'nonprofit',
    'ltd', 'inc', 'corp',                       -- Canadian
    'lp', 'llp',                                -- partnerships
    'pllc', 'pc'                                -- professional
  ));

-- Convenience: derive country from jurisdictions when a row is inserted
-- without an explicit country (backfill support).
UPDATE formation_orders
   SET country = COALESCE(j.country, 'US')
  FROM jurisdictions j
 WHERE formation_orders.state_code = j.code
   AND formation_orders.country = 'US';   -- only touch default rows

-- ──────────────────────────────────────────────────────────────────────
-- 3. canada_crtc_orders: province column
-- ──────────────────────────────────────────────────────────────────────

ALTER TABLE canada_crtc_orders
  ADD COLUMN IF NOT EXISTS province CHAR(2) NOT NULL DEFAULT 'BC'
    CHECK (province IN ('BC','ON','AB','QC','MB','SK','NS','NB','NL','PE'));

CREATE INDEX IF NOT EXISTS idx_canada_crtc_orders_province
  ON canada_crtc_orders(province);

-- ──────────────────────────────────────────────────────────────────────
-- 4. foreign_qualification_registrations
-- ──────────────────────────────────────────────────────────────────────
--
-- A foreign qualification (aka "Certificate of Authority") is what a
-- company formed in State A files in State B to be allowed to do
-- business in State B.  FCC carriers typically need one per state they
-- serve; regular formation clients may add a few as an expansion.
--
-- This table tracks each per-state filing as its own lifecycle, but all
-- filings for one order share a single parent compliance_orders row.
-- That way a 20-state FCC order is one checkout + one invoice with 20
-- independent filings + state fee obligations.
--
-- Why not reuse formation_orders: formation_orders is scoped to creating
-- a NEW entity; foreign qualification operates on an EXISTING entity.
-- Different schema (no entity_name_alt, no members, etc.), different
-- lifecycle.

CREATE TABLE IF NOT EXISTS foreign_qualification_registrations (
    id                      BIGSERIAL PRIMARY KEY,

    -- Parent order (compliance_orders row; one order can fan out to
    -- many states).
    compliance_order_id     INTEGER REFERENCES compliance_orders(id) ON DELETE SET NULL,
    order_number            TEXT NOT NULL,

    -- Linked existing entity (if ordered on an already-registered
    -- carrier).  For FCC clients this is telecom_entities.id.  For
    -- non-FCC formation expansion, nullable with legal_name /
    -- home_state_code filled in directly.
    telecom_entity_id       INTEGER,      -- FK enforced softly via app logic

    -- Source / home jurisdiction — where the entity was originally formed.
    home_country            CHAR(2) NOT NULL DEFAULT 'US'
                            CHECK (home_country IN ('US','CA')),
    home_state_code         CHAR(2) NOT NULL,

    -- Target jurisdiction — where we're filing the COA.
    target_state_code       CHAR(2) NOT NULL,

    -- Entity info captured at order time.  We don't trust telecom_entities
    -- to be complete so we snapshot it here, mirroring how compliance
    -- orders snapshot legal_name / address.
    entity_legal_name       TEXT NOT NULL,
    entity_type             TEXT NOT NULL,        -- 'llc' | 'corporation' | etc.
    formed_on               DATE,                 -- original formation date
    home_state_filing_number TEXT,                -- original charter #
    ein                     TEXT,

    -- Principal + target-state address
    principal_address_json  JSONB,                -- {street, city, state, zip}
    registered_agent_name   TEXT,                 -- RA in the TARGET state
    registered_agent_address_json JSONB,
    include_ra_service      BOOLEAN NOT NULL DEFAULT TRUE,
      -- NWRA provisioning — we resell their address as RA-in-target-state.

    -- Money.  Cents convention — target state fee + service fee + NWRA
    -- wholesale cost; retail_total_cents matches the compliance_order
    -- line for this state.
    state_fee_cents         INTEGER NOT NULL DEFAULT 0,
    expedited               BOOLEAN NOT NULL DEFAULT FALSE,
    expedited_fee_cents     INTEGER NOT NULL DEFAULT 0,
    nwra_wholesale_cents    INTEGER NOT NULL DEFAULT 0,
    service_fee_cents       INTEGER NOT NULL DEFAULT 0,
    retail_total_cents      INTEGER NOT NULL DEFAULT 0,

    -- Documents required for the target state's filing (varies widely):
    --   good_standing: certificate of good standing from home state
    --   articles:       articles of incorporation from home state
    --   name_reservation: if target state requires one
    --   publication:    e.g. NY, AZ, NE require newspaper publication
    supporting_docs_json    JSONB NOT NULL DEFAULT '{}'::jsonb,

    -- Pipeline state per filing.
    status                  TEXT NOT NULL DEFAULT 'received' CHECK (status IN (
                              'received',          -- paid, queued
                              'docs_pending',      -- waiting on good-standing cert
                              'filing',            -- portal automation running
                              'admin_review',      -- manual step needed
                              'submitted',         -- filed, awaiting state approval
                              'approved',          -- COA issued
                              'rejected',
                              'cancelled'
                            )),
    state_filing_number     TEXT,                  -- returned by portal
    state_confirmation_url  TEXT,
    filed_at                TIMESTAMPTZ,
    approved_at             TIMESTAMPTZ,
    coa_minio_path          TEXT,                  -- stored Certificate of Authority

    -- Errors + ops
    last_error              TEXT,
    attempt_count           INTEGER NOT NULL DEFAULT 0,
    admin_todo_id           INTEGER,               -- ERPNext ToDo if manual

    notes                   TEXT,
    created_at              TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at              TIMESTAMPTZ NOT NULL DEFAULT NOW(),

    -- A carrier only needs ONE active foreign qualification per target
    -- state — we don't want to accept a duplicate order.  Application
    -- should look for WHERE status NOT IN ('cancelled','rejected').
    UNIQUE (telecom_entity_id, target_state_code,
            order_number)  -- order_number breaks ties for re-orders
);

CREATE INDEX IF NOT EXISTS idx_fq_order_number
  ON foreign_qualification_registrations(order_number);
CREATE INDEX IF NOT EXISTS idx_fq_target_state
  ON foreign_qualification_registrations(target_state_code);
CREATE INDEX IF NOT EXISTS idx_fq_status
  ON foreign_qualification_registrations(status)
  WHERE status NOT IN ('approved','cancelled','rejected');
CREATE INDEX IF NOT EXISTS idx_fq_telecom_entity
  ON foreign_qualification_registrations(telecom_entity_id)
  WHERE telecom_entity_id IS NOT NULL;

-- Updated_at trigger — keep it in sync with the pattern used elsewhere.
-- We add a dedicated trigger function if one doesn't exist already.
CREATE OR REPLACE FUNCTION set_updated_at_fq() RETURNS trigger AS $$
BEGIN
  NEW.updated_at = NOW();
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS trg_fq_updated_at ON foreign_qualification_registrations;
CREATE TRIGGER trg_fq_updated_at
  BEFORE UPDATE ON foreign_qualification_registrations
  FOR EACH ROW EXECUTE FUNCTION set_updated_at_fq();

-- ──────────────────────────────────────────────────────────────────────
-- 5. View: admin dashboard pipeline
-- ──────────────────────────────────────────────────────────────────────

CREATE OR REPLACE VIEW v_foreign_qualifications_pipeline AS
SELECT
  fq.id,
  fq.order_number,
  fq.entity_legal_name,
  fq.home_state_code,
  fq.target_state_code,
  j.name            AS target_state_name,
  fq.entity_type,
  fq.status,
  fq.filed_at,
  fq.approved_at,
  fq.retail_total_cents,
  fq.attempt_count,
  fq.last_error,
  fq.created_at
FROM foreign_qualification_registrations fq
LEFT JOIN jurisdictions j ON j.code = fq.target_state_code
ORDER BY fq.created_at DESC;

COMMIT;
