-- ============================================================
-- MulliganMates — Initial Schema
-- ============================================================

-- Profiles (extends auth.users)
create table public.profiles (
  id              uuid primary key references auth.users on delete cascade,
  display_name    text not null,
  avatar_url      text,
  handicap_index  numeric(4,1) check (handicap_index between -10 and 54),
  created_at      timestamptz not null default now()
);

-- Automatically create a profile when a new user is confirmed
create or replace function public.handle_new_user()
returns trigger language plpgsql security definer set search_path = public
as $$
begin
  insert into public.profiles (id, display_name)
  values (new.id, coalesce(new.raw_user_meta_data->>'display_name', split_part(new.email, '@', 1)));
  return new;
end;
$$;

create trigger on_auth_user_created
  after insert on auth.users
  for each row execute procedure public.handle_new_user();

-- ============================================================
-- Courses
-- ============================================================
create table public.courses (
  id          uuid primary key default gen_random_uuid(),
  name        text not null,
  par         int  not null check (par between 27 and 90),
  created_by  uuid not null references public.profiles on delete set null,
  created_at  timestamptz not null default now()
);

-- Tees per course
create table public.tees (
  id             uuid primary key default gen_random_uuid(),
  course_id      uuid not null references public.courses on delete cascade,
  name           text not null,       -- e.g. "Yellow", "White", "Blue"
  color          text not null default '#888888',
  course_rating  numeric(4,1) not null,
  slope_rating   int  not null check (slope_rating between 55 and 155),
  created_at     timestamptz not null default now()
);

-- Holes (shared across tees on the same course)
create table public.holes (
  id            uuid primary key default gen_random_uuid(),
  course_id     uuid not null references public.courses on delete cascade,
  hole_number   int  not null check (hole_number between 1 and 18),
  par           int  not null check (par between 3 and 5),
  stroke_index  int  not null check (stroke_index between 1 and 18),
  unique (course_id, hole_number)
);

-- Validate that sum of hole pars equals the course par
create or replace function public.check_course_par()
returns trigger language plpgsql as $$
declare
  total_par int;
  course_par int;
  hole_count int;
begin
  select count(*), sum(h.par)
    into hole_count, total_par
    from public.holes h
   where h.course_id = new.course_id;

  select c.par into course_par
    from public.courses c
   where c.id = new.course_id;

  -- Only enforce once all holes are entered (9 or 18)
  if hole_count in (9, 18) then
    if total_par <> course_par then
      raise exception 'Sum of hole pars (%) does not equal course par (%)',
        total_par, course_par;
    end if;
  end if;

  return new;
end;
$$;

create trigger enforce_course_par
  after insert or update on public.holes
  for each row execute procedure public.check_course_par();

-- ============================================================
-- Rounds
-- ============================================================
create type public.round_status as enum ('lobby', 'active', 'completed');

create table public.rounds (
  id           uuid primary key default gen_random_uuid(),
  course_id    uuid not null references public.courses,
  tee_id       uuid not null references public.tees,
  name         text,
  date         date not null default current_date,
  holes_count  int  not null check (holes_count in (9, 18)),
  status       public.round_status not null default 'lobby',
  created_by   uuid not null references public.profiles,
  created_at   timestamptz not null default now()
);

-- Players in a round
create table public.round_players (
  id               uuid primary key default gen_random_uuid(),
  round_id         uuid not null references public.rounds on delete cascade,
  user_id          uuid not null references public.profiles on delete cascade,
  role             text not null default 'player' check (role in ('admin', 'player')),
  handicap_index   numeric(4,1),
  course_handicap  int,
  joined_at        timestamptz not null default now(),
  unique (round_id, user_id)
);

-- Round invitations
create table public.round_invites (
  id          uuid primary key default gen_random_uuid(),
  round_id    uuid not null references public.rounds on delete cascade,
  email       text not null,
  invited_by  uuid not null references public.profiles,
  accepted_at timestamptz,
  expires_at  timestamptz not null default (now() + interval '7 days'),
  created_at  timestamptz not null default now()
);

-- ============================================================
-- Scores
-- ============================================================
create table public.scores (
  id          uuid primary key default gen_random_uuid(),
  round_id    uuid not null references public.rounds on delete cascade,
  hole_id     uuid not null references public.holes on delete cascade,
  player_id   uuid not null references public.profiles on delete cascade,
  strokes     int  not null check (strokes > 0),
  updated_by  uuid not null references public.profiles,
  updated_at  timestamptz not null default now(),
  unique (round_id, hole_id, player_id)
);

-- Update updated_at on score change
create or replace function public.set_score_updated_at()
returns trigger language plpgsql as $$
begin
  new.updated_at = now();
  return new;
end;
$$;

create trigger scores_updated_at
  before update on public.scores
  for each row execute procedure public.set_score_updated_at();
