-- =====================================================================
--  TeeCup — migrasjon 065
--  GolfAPI.io som tredje banekilde (ADR-064) -- baner utenfor TeeOffs
--  dekning (f.eks. Tjøme Golfklubb, bekreftet IKKE i TeeOff 2026-08-12).
-- =====================================================================
--  GolfAPI-kall koster ekte, begrenset budsjett (kjøpt 20 kall, ~2/bane)
--  -- ULIKT TeeOffs frie, offentlige API. Derfor: ETT delt, globalt
--  cache-lag (golfapi_course + underliggende hull/tee/koordinat-tabeller)
--  som ALDRI hentes på nytt for samme fysiske bane (GolfAPIs avtale
--  tillater eksplisitt permanent caching). Både den org-scopede
--  turneringsmodellen (course/hole/tee/tee_rating) OG den globale
--  personal_course-katalogen (migrasjon 020) kopierer INN fra denne
--  cachen ved eksplisitt import -- selve cachen eies ikke av noen av de
--  to, den er en tredje, uavhengig katalog.
--
--  Koordinatene (grønn front/midt/bak, hindringer, tee-punkter) kopieres
--  ALDRI inn per import -- de er ikke en del av HCP-beregningen (ingen
--  reproduserbarhets-hensyn som par/rating har via ADR-007/ADR-019), så
--  rangefinder-oppslag leser alltid direkte fra golfapi_course_coordinate
--  via banens lagrede GolfAPI-courseID. Én fysisk bane = ett
--  koordinatsett, uansett hvor mange ganger den importeres.
-- =====================================================================

\set ON_ERROR_STOP on

-- ---------------------------------------------------------------------
-- Delt GolfAPI-cache (global, ingen organization_id/owner -- én rad per
-- fysisk bane som NOEN i TeeCup noensinne har importert)
-- ---------------------------------------------------------------------

-- GolfAPIs courseID brukes direkte som PK (globalt unik hos dem, ingen
-- grunn til en egen surrogate-nøkkel).
CREATE TABLE golfapi_course (
    course_id          text PRIMARY KEY,
    club_id            text NOT NULL,
    club_name          text NOT NULL,
    course_name        text NOT NULL,
    city               text,
    country             text,
    num_holes          smallint NOT NULL CHECK (num_holes BETWEEN 1 AND 18),
    -- Alltid hentet med measureUnit=m (golfapi_client.py) -- ingen yard-data
    -- lagres, unngår enhets-fellen research allerede advarte om.
    has_gps            boolean NOT NULL DEFAULT false,
    num_coordinates    integer NOT NULL DEFAULT 0,
    golfapi_updated_at timestamptz,     -- deres timestampUpdated, til evt. fremtidig re-sync-vurdering
    fetched_at         timestamptz NOT NULL DEFAULT now()
);

-- Par/SI per hull. Kun menns verdier er kanonisk brukt av kopier-inn-
-- stegene under (TeeCups eksisterende hole/personal_course_hole har
-- ingen kjønnsdelt par -- samme forenkling som TeeOff-importen, ADR-019).
-- Kvinners verdier caches likevel, i tilfelle en fremtidig utvidelse.
CREATE TABLE golfapi_course_hole (
    id                 uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    golfapi_course_id  text NOT NULL REFERENCES golfapi_course(course_id) ON DELETE CASCADE,
    hole_number        smallint NOT NULL CHECK (hole_number BETWEEN 1 AND 18),
    par_men            smallint NOT NULL CHECK (par_men BETWEEN 3 AND 6),
    index_men          smallint NOT NULL CHECK (index_men BETWEEN 1 AND 18),
    par_women          smallint CHECK (par_women BETWEEN 3 AND 6),
    index_women        smallint CHECK (index_women BETWEEN 1 AND 18),
    UNIQUE (golfapi_course_id, hole_number),
    UNIQUE (golfapi_course_id, index_men)
);

CREATE TABLE golfapi_course_tee (
    id                       uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    golfapi_course_id        text NOT NULL REFERENCES golfapi_course(course_id) ON DELETE CASCADE,
    golfapi_tee_id           text NOT NULL,
    name                     text NOT NULL,
    color_hex                text,
    -- Meter per hull, indeks 0 = hull 1 ... indeks 17 = hull 18.
    lengths_meters           smallint[] NOT NULL,
    course_rating_men        numeric(4,1) NOT NULL,
    slope_men                smallint NOT NULL CHECK (slope_men BETWEEN 55 AND 155),
    course_rating_women      numeric(4,1),
    slope_women              smallint CHECK (slope_women BETWEEN 55 AND 155),
    course_rating_men_front9 numeric(4,1),
    course_rating_men_back9  numeric(4,1),
    course_rating_women_front9 numeric(4,1),
    course_rating_women_back9  numeric(4,1),
    UNIQUE (golfapi_course_id, golfapi_tee_id),
    CHECK (array_length(lengths_meters, 1) BETWEEN 1 AND 18)
);

-- Rangefinder-datalaget: grønn front/midt/bak, hindringer, tee-punkter.
-- poi_type/green_location/side_fairway holdes som tekst+CHECK (ikke
-- egne enum-typer) -- samme "kan utvides uten ALTER TYPE"-begrunnelse
-- som 001 allerede bruker for `format`.
CREATE TABLE golfapi_course_coordinate (
    id                 uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    golfapi_course_id  text NOT NULL REFERENCES golfapi_course(course_id) ON DELETE CASCADE,
    hole_number        smallint NOT NULL CHECK (hole_number BETWEEN 1 AND 18),
    poi_type           text NOT NULL CHECK (poi_type IN (
                            'green', 'green_bunker', 'fairway_bunker', 'water',
                            'trees', 'marker_100', 'marker_150', 'marker_200',
                            'dogleg', 'road', 'tee_front', 'tee_back'
                        )),
    -- GolfAPIs `location`-felt er generisk (front/midt/bak for POI-et),
    -- ikke kun for 'green' -- f.eks. hadde Tjømes bunkere også front/bak.
    -- Ikke navngitt green_location -- ville feilaktig antydet at kun
    -- grønn-punkter har denne verdien.
    location           text CHECK (location IN ('front', 'middle', 'back')),
    side_fairway       text CHECK (side_fairway IN ('left', 'center', 'right')),
    latitude           double precision NOT NULL CHECK (latitude  BETWEEN -90  AND 90),
    longitude          double precision NOT NULL CHECK (longitude BETWEEN -180 AND 180)
);

CREATE INDEX ON golfapi_course_hole       (golfapi_course_id);
CREATE INDEX ON golfapi_course_tee        (golfapi_course_id);
CREATE INDEX ON golfapi_course_coordinate (golfapi_course_id, hole_number);

GRANT SELECT, INSERT, UPDATE, DELETE ON golfapi_course            TO teecup_app;
GRANT SELECT, INSERT, UPDATE, DELETE ON golfapi_course_hole       TO teecup_app;
GRANT SELECT, INSERT, UPDATE, DELETE ON golfapi_course_tee        TO teecup_app;
GRANT SELECT, INSERT, UPDATE, DELETE ON golfapi_course_coordinate TO teecup_app;

-- ---------------------------------------------------------------------
-- Kopier-inn-mål 1: org-scopet turneringsbane (course), ny kilde
-- ---------------------------------------------------------------------
-- Samme mønster som ADR-019s 'official' (teeoff) -- men 'international'
-- betyr GolfAPI, IKKE live-oppslag (Beslutning i ADR-064: GolfAPI-kall
-- koster budsjett, teeoffs gjør ikke -- derfor kopier-inn her også).
ALTER TYPE course_source ADD VALUE 'international';

-- CHECK-constraint kan ikke endres direkte -- droppes og gjenopprettes
-- med samme betingelse utvidet symmetrisk. Navnet (course_check) er
-- Postgres sitt auto-genererte navn for det opprinnelige, unavngitte
-- table-level CHECK-et i 001 -- bekreftet mot ekte teecup_db, ikke gjettet.
ALTER TABLE course DROP CONSTRAINT course_check;
ALTER TABLE course ADD CONSTRAINT course_check
    CHECK (source NOT IN ('official', 'international') OR external_course_ref IS NOT NULL);

-- ---------------------------------------------------------------------
-- Kopier-inn-mål 2: global personal_course-katalog, ny provenance-kolonne
-- ---------------------------------------------------------------------
-- round.course_source trenger INGEN endring -- en GolfAPI-importert bane
-- blir en helt vanlig personal_course-rad (course_source='custom' i
-- round, uendret), kun med denne kolonnen satt for å (a) hindre
-- dupliserte importer, (b) la rangefinder-oppslag finne koordinatene.
ALTER TABLE personal_course
    ADD COLUMN external_golfapi_course_id text REFERENCES golfapi_course(course_id);

CREATE UNIQUE INDEX personal_course_golfapi_ref_unique
    ON personal_course (external_golfapi_course_id)
    WHERE external_golfapi_course_id IS NOT NULL;
