/*
 * -------------------------------------------------------
 * Fischerei (Fishing Association Management) Schema
 * Waters, species, stocking, leases, catch books,
 * catches, permits, inspectors, competitions
 * -------------------------------------------------------
 */

-- =====================================================
-- 1. Enums
-- =====================================================

CREATE TYPE public.water_type AS ENUM(
  'fluss', 'bach', 'see', 'teich', 'weiher', 'kanal', 'stausee', 'baggersee', 'sonstige'
);

CREATE TYPE public.fish_age_class AS ENUM(
  'brut', 'soemmerlinge', 'einsoemmerig', 'zweisoemmerig', 'dreisoemmerig', 'vorgestreckt', 'setzlinge', 'laichfische', 'sonstige'
);

CREATE TYPE public.catch_book_status AS ENUM(
  'offen', 'eingereicht', 'geprueft', 'akzeptiert', 'abgelehnt'
);

CREATE TYPE public.catch_book_verification AS ENUM(
  'sehrgut', 'gut', 'ok', 'schlecht', 'falsch', 'leer'
);

CREATE TYPE public.lease_payment_method AS ENUM(
  'bar', 'lastschrift', 'ueberweisung'
);

CREATE TYPE public.fish_gender AS ENUM(
  'maennlich', 'weiblich', 'unbekannt'
);

CREATE TYPE public.fish_size_category AS ENUM(
  'gross', 'mittel', 'klein'
);

-- =====================================================
-- 2. Extend app_permissions
-- (Moved to 20260411900001_fischerei_enum_values.sql — Postgres requires
--  new enum values to be committed in a separate transaction)
-- =====================================================

-- =====================================================
-- 3. cost_centers (shared, may already exist)
-- =====================================================

CREATE TABLE IF NOT EXISTS public.cost_centers (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
  name text NOT NULL,
  code text,
  description text,
  is_active boolean NOT NULL DEFAULT true,
  created_at timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS ix_cost_centers_account ON public.cost_centers(account_id);
ALTER TABLE public.cost_centers ENABLE ROW LEVEL SECURITY;
REVOKE ALL ON public.cost_centers FROM authenticated, service_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.cost_centers TO authenticated;
GRANT ALL ON public.cost_centers TO service_role;

CREATE POLICY cost_centers_select ON public.cost_centers FOR SELECT TO authenticated
  USING (public.has_role_on_account(account_id));
CREATE POLICY cost_centers_mutate ON public.cost_centers FOR ALL TO authenticated
  USING (public.has_permission(auth.uid(), account_id, 'finance.write'::public.app_permissions));

-- =====================================================
-- 4. fish_suppliers
-- =====================================================

CREATE TABLE IF NOT EXISTS public.fish_suppliers (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
  name text NOT NULL,
  contact_person text,
  phone text,
  email text,
  address text,
  notes text,
  is_active boolean NOT NULL DEFAULT true,
  created_at timestamptz NOT NULL DEFAULT now(),
  updated_at timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX ix_fish_suppliers_account ON public.fish_suppliers(account_id);
ALTER TABLE public.fish_suppliers ENABLE ROW LEVEL SECURITY;
REVOKE ALL ON public.fish_suppliers FROM authenticated, service_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.fish_suppliers TO authenticated;
GRANT ALL ON public.fish_suppliers TO service_role;

CREATE POLICY fish_suppliers_select ON public.fish_suppliers FOR SELECT TO authenticated
  USING (public.has_role_on_account(account_id));
CREATE POLICY fish_suppliers_insert ON public.fish_suppliers FOR INSERT TO authenticated
  WITH CHECK (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));
CREATE POLICY fish_suppliers_update ON public.fish_suppliers FOR UPDATE TO authenticated
  USING (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));
CREATE POLICY fish_suppliers_delete ON public.fish_suppliers FOR DELETE TO authenticated
  USING (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));

CREATE TRIGGER trg_fish_suppliers_updated_at
  BEFORE UPDATE ON public.fish_suppliers
  FOR EACH ROW EXECUTE FUNCTION public.update_account_settings_timestamp();

-- =====================================================
-- 5. waters (ve_gewaesser)
-- =====================================================

CREATE TABLE IF NOT EXISTS public.waters (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,

  -- Identity
  name text NOT NULL,
  short_name text,
  water_type public.water_type NOT NULL DEFAULT 'sonstige',
  description text,

  -- Dimensions
  surface_area_ha numeric(10,2),
  length_m numeric(10,0),
  width_m numeric(10,2),
  avg_depth_m numeric(6,2),
  max_depth_m numeric(6,2),

  -- Geography
  outflow text,
  location text,
  classification_order integer,
  county text,
  geo_lat numeric(10,7),
  geo_lng numeric(10,7),

  -- LFV (Landesfischereiverband)
  lfv_number text,
  lfv_name text,

  -- Cost allocation
  cost_share_ds numeric(5,2) DEFAULT 0,
  cost_share_kalk numeric(5,2) DEFAULT 0,

  -- Electrofishing
  electrofishing_permit_requested boolean NOT NULL DEFAULT false,

  -- HejFish integration
  hejfish_id text,

  -- References
  cost_center_id uuid REFERENCES public.cost_centers(id) ON DELETE SET NULL,

  -- Flags
  is_archived boolean NOT NULL DEFAULT false,

  -- Meta
  created_by uuid REFERENCES auth.users(id) ON DELETE SET NULL,
  updated_by uuid REFERENCES auth.users(id) ON DELETE SET NULL,
  created_at timestamptz NOT NULL DEFAULT now(),
  updated_at timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX ix_waters_account ON public.waters(account_id);
CREATE INDEX ix_waters_name ON public.waters(account_id, name);
CREATE INDEX ix_waters_type ON public.waters(account_id, water_type);
CREATE INDEX ix_waters_archived ON public.waters(account_id, is_archived);

ALTER TABLE public.waters ENABLE ROW LEVEL SECURITY;
REVOKE ALL ON public.waters FROM authenticated, service_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.waters TO authenticated;
GRANT ALL ON public.waters TO service_role;

CREATE POLICY waters_select ON public.waters FOR SELECT TO authenticated
  USING (public.has_role_on_account(account_id));
CREATE POLICY waters_insert ON public.waters FOR INSERT TO authenticated
  WITH CHECK (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));
CREATE POLICY waters_update ON public.waters FOR UPDATE TO authenticated
  USING (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));
CREATE POLICY waters_delete ON public.waters FOR DELETE TO authenticated
  USING (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));

CREATE TRIGGER trg_waters_updated_at
  BEFORE UPDATE ON public.waters
  FOR EACH ROW EXECUTE FUNCTION public.update_account_settings_timestamp();

-- =====================================================
-- 6. fish_species (ve_fischarten)
-- =====================================================

CREATE TABLE IF NOT EXISTS public.fish_species (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,

  -- Names
  name text NOT NULL,
  name_latin text,
  name_local text,

  -- Status
  is_active boolean NOT NULL DEFAULT true,

  -- Biometrics
  max_age_years integer,
  max_weight_kg numeric(8,2),
  max_length_cm numeric(6,1),

  -- Protection (Schonmaß / Schonzeit)
  protected_min_size_cm numeric(5,1),
  protection_period_start text, -- MM.DD format
  protection_period_end text,   -- MM.DD format

  -- Spawning season (Sonderschonzeit / SZG)
  spawning_season_start text,   -- MM.DD format
  spawning_season_end text,     -- MM.DD format
  has_special_spawning_season boolean NOT NULL DEFAULT false,

  -- Condition factor (K-Faktor)
  k_factor_avg numeric(6,3),
  k_factor_min numeric(6,3),
  k_factor_max numeric(6,3),

  -- Quotas
  price_per_unit numeric(8,2),
  max_catch_per_day integer,
  max_catch_per_year integer,

  -- Recording
  individual_recording boolean NOT NULL DEFAULT false,

  -- Meta
  sort_order integer NOT NULL DEFAULT 0,
  created_at timestamptz NOT NULL DEFAULT now(),
  updated_at timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX ix_fish_species_account ON public.fish_species(account_id);
CREATE INDEX ix_fish_species_name ON public.fish_species(account_id, name);
CREATE INDEX ix_fish_species_active ON public.fish_species(account_id, is_active);

ALTER TABLE public.fish_species ENABLE ROW LEVEL SECURITY;
REVOKE ALL ON public.fish_species FROM authenticated, service_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.fish_species TO authenticated;
GRANT ALL ON public.fish_species TO service_role;

CREATE POLICY fish_species_select ON public.fish_species FOR SELECT TO authenticated
  USING (public.has_role_on_account(account_id));
CREATE POLICY fish_species_insert ON public.fish_species FOR INSERT TO authenticated
  WITH CHECK (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));
CREATE POLICY fish_species_update ON public.fish_species FOR UPDATE TO authenticated
  USING (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));
CREATE POLICY fish_species_delete ON public.fish_species FOR DELETE TO authenticated
  USING (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));

CREATE TRIGGER trg_fish_species_updated_at
  BEFORE UPDATE ON public.fish_species
  FOR EACH ROW EXECUTE FUNCTION public.update_account_settings_timestamp();

-- =====================================================
-- 7. water_species_rules (ve_gewaesser_fischart)
-- =====================================================

CREATE TABLE IF NOT EXISTS public.water_species_rules (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  water_id uuid NOT NULL REFERENCES public.waters(id) ON DELETE CASCADE,
  species_id uuid NOT NULL REFERENCES public.fish_species(id) ON DELETE CASCADE,

  -- Overrides (null = use species default)
  min_size_cm numeric(5,1),
  protection_period_start text,
  protection_period_end text,
  max_catch_per_day integer,
  max_catch_per_year integer,

  created_at timestamptz NOT NULL DEFAULT now(),
  UNIQUE(water_id, species_id)
);

CREATE INDEX ix_water_species_rules_water ON public.water_species_rules(water_id);
CREATE INDEX ix_water_species_rules_species ON public.water_species_rules(species_id);

ALTER TABLE public.water_species_rules ENABLE ROW LEVEL SECURITY;
REVOKE ALL ON public.water_species_rules FROM authenticated, service_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.water_species_rules TO authenticated;
GRANT ALL ON public.water_species_rules TO service_role;

CREATE POLICY water_species_rules_select ON public.water_species_rules FOR SELECT TO authenticated
  USING (EXISTS (SELECT 1 FROM public.waters w WHERE w.id = water_species_rules.water_id AND public.has_role_on_account(w.account_id)));
CREATE POLICY water_species_rules_mutate ON public.water_species_rules FOR ALL TO authenticated
  USING (EXISTS (SELECT 1 FROM public.waters w WHERE w.id = water_species_rules.water_id AND public.has_permission(auth.uid(), w.account_id, 'fischerei.write'::public.app_permissions)));

-- =====================================================
-- 8. fish_stocking (ve_besatz)
-- =====================================================

CREATE TABLE IF NOT EXISTS public.fish_stocking (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
  water_id uuid NOT NULL REFERENCES public.waters(id) ON DELETE CASCADE,
  species_id uuid NOT NULL REFERENCES public.fish_species(id) ON DELETE RESTRICT,

  stocking_date date NOT NULL,
  quantity integer NOT NULL DEFAULT 0,
  weight_kg numeric(8,2),
  age_class public.fish_age_class NOT NULL DEFAULT 'sonstige',
  cost_euros numeric(10,2),
  supplier_id uuid REFERENCES public.fish_suppliers(id) ON DELETE SET NULL,
  remarks text,

  created_by uuid REFERENCES auth.users(id) ON DELETE SET NULL,
  updated_by uuid REFERENCES auth.users(id) ON DELETE SET NULL,
  created_at timestamptz NOT NULL DEFAULT now(),
  updated_at timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX ix_fish_stocking_account ON public.fish_stocking(account_id);
CREATE INDEX ix_fish_stocking_water ON public.fish_stocking(water_id);
CREATE INDEX ix_fish_stocking_species ON public.fish_stocking(species_id);
CREATE INDEX ix_fish_stocking_date ON public.fish_stocking(stocking_date DESC);

ALTER TABLE public.fish_stocking ENABLE ROW LEVEL SECURITY;
REVOKE ALL ON public.fish_stocking FROM authenticated, service_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.fish_stocking TO authenticated;
GRANT ALL ON public.fish_stocking TO service_role;

CREATE POLICY fish_stocking_select ON public.fish_stocking FOR SELECT TO authenticated
  USING (public.has_role_on_account(account_id));
CREATE POLICY fish_stocking_insert ON public.fish_stocking FOR INSERT TO authenticated
  WITH CHECK (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));
CREATE POLICY fish_stocking_update ON public.fish_stocking FOR UPDATE TO authenticated
  USING (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));
CREATE POLICY fish_stocking_delete ON public.fish_stocking FOR DELETE TO authenticated
  USING (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));

CREATE TRIGGER trg_fish_stocking_updated_at
  BEFORE UPDATE ON public.fish_stocking
  FOR EACH ROW EXECUTE FUNCTION public.update_account_settings_timestamp();

-- =====================================================
-- 9. fishing_leases (ve_pachten)
-- =====================================================

CREATE TABLE IF NOT EXISTS public.fishing_leases (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
  water_id uuid NOT NULL REFERENCES public.waters(id) ON DELETE CASCADE,

  -- Lessor
  lessor_name text NOT NULL,
  lessor_address text,
  lessor_phone text,
  lessor_email text,

  -- Lease terms
  start_date date NOT NULL,
  end_date date,
  duration_years integer,
  initial_amount numeric(10,2) NOT NULL DEFAULT 0,
  fixed_annual_increase numeric(10,2) DEFAULT 0,
  percentage_annual_increase numeric(5,2) DEFAULT 0,

  -- Payment
  payment_method public.lease_payment_method DEFAULT 'ueberweisung',
  account_holder text,
  iban text,
  bic text,

  -- Location details
  location_details text,
  special_agreements text,

  -- Status
  is_archived boolean NOT NULL DEFAULT false,

  -- Meta
  created_by uuid REFERENCES auth.users(id) ON DELETE SET NULL,
  updated_by uuid REFERENCES auth.users(id) ON DELETE SET NULL,
  created_at timestamptz NOT NULL DEFAULT now(),
  updated_at timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX ix_fishing_leases_account ON public.fishing_leases(account_id);
CREATE INDEX ix_fishing_leases_water ON public.fishing_leases(water_id);
CREATE INDEX ix_fishing_leases_dates ON public.fishing_leases(start_date, end_date);

ALTER TABLE public.fishing_leases ENABLE ROW LEVEL SECURITY;
REVOKE ALL ON public.fishing_leases FROM authenticated, service_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.fishing_leases TO authenticated;
GRANT ALL ON public.fishing_leases TO service_role;

CREATE POLICY fishing_leases_select ON public.fishing_leases FOR SELECT TO authenticated
  USING (public.has_role_on_account(account_id));
CREATE POLICY fishing_leases_insert ON public.fishing_leases FOR INSERT TO authenticated
  WITH CHECK (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));
CREATE POLICY fishing_leases_update ON public.fishing_leases FOR UPDATE TO authenticated
  USING (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));
CREATE POLICY fishing_leases_delete ON public.fishing_leases FOR DELETE TO authenticated
  USING (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));

CREATE TRIGGER trg_fishing_leases_updated_at
  BEFORE UPDATE ON public.fishing_leases
  FOR EACH ROW EXECUTE FUNCTION public.update_account_settings_timestamp();

-- =====================================================
-- 10. fishing_permits (ve_gewaesserkarten)
-- =====================================================

CREATE TABLE IF NOT EXISTS public.fishing_permits (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
  name text NOT NULL,
  short_code text,
  primary_water_id uuid REFERENCES public.waters(id) ON DELETE SET NULL,
  total_quantity integer,
  cost_center_id uuid REFERENCES public.cost_centers(id) ON DELETE SET NULL,
  hejfish_id text,
  is_for_sale boolean NOT NULL DEFAULT true,
  is_archived boolean NOT NULL DEFAULT false,
  created_at timestamptz NOT NULL DEFAULT now(),
  updated_at timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX ix_fishing_permits_account ON public.fishing_permits(account_id);
ALTER TABLE public.fishing_permits ENABLE ROW LEVEL SECURITY;
REVOKE ALL ON public.fishing_permits FROM authenticated, service_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.fishing_permits TO authenticated;
GRANT ALL ON public.fishing_permits TO service_role;

CREATE POLICY fishing_permits_select ON public.fishing_permits FOR SELECT TO authenticated
  USING (public.has_role_on_account(account_id));
CREATE POLICY fishing_permits_mutate ON public.fishing_permits FOR ALL TO authenticated
  USING (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));

CREATE TRIGGER trg_fishing_permits_updated_at
  BEFORE UPDATE ON public.fishing_permits
  FOR EACH ROW EXECUTE FUNCTION public.update_account_settings_timestamp();

-- =====================================================
-- 11. permit_quotas (ve_gewaesserk_kontingent)
-- =====================================================

CREATE TABLE IF NOT EXISTS public.permit_quotas (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  permit_id uuid NOT NULL REFERENCES public.fishing_permits(id) ON DELETE CASCADE,
  business_year integer NOT NULL,
  category_name text,
  quota_quantity integer NOT NULL DEFAULT 0,
  conversion_factor numeric(5,2) DEFAULT 1.00,
  created_at timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX ix_permit_quotas_permit ON public.permit_quotas(permit_id);
ALTER TABLE public.permit_quotas ENABLE ROW LEVEL SECURITY;
REVOKE ALL ON public.permit_quotas FROM authenticated, service_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.permit_quotas TO authenticated;
GRANT ALL ON public.permit_quotas TO service_role;

CREATE POLICY permit_quotas_select ON public.permit_quotas FOR SELECT TO authenticated
  USING (EXISTS (SELECT 1 FROM public.fishing_permits p WHERE p.id = permit_quotas.permit_id AND public.has_role_on_account(p.account_id)));
CREATE POLICY permit_quotas_mutate ON public.permit_quotas FOR ALL TO authenticated
  USING (EXISTS (SELECT 1 FROM public.fishing_permits p WHERE p.id = permit_quotas.permit_id AND public.has_permission(auth.uid(), p.account_id, 'fischerei.write'::public.app_permissions)));

-- =====================================================
-- 12. catch_books (ve_mitglieder_fangbuch)
-- =====================================================

CREATE TABLE IF NOT EXISTS public.catch_books (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
  member_id uuid NOT NULL REFERENCES public.members(id) ON DELETE CASCADE,
  year integer NOT NULL,

  -- Denormalized for reporting
  member_name text,
  member_birth_date date,

  -- Usage
  fishing_days_count integer NOT NULL DEFAULT 0,
  total_fish_caught integer NOT NULL DEFAULT 0,

  -- Associated permits
  card_numbers text,
  is_fly_fisher boolean NOT NULL DEFAULT false,

  -- Verification workflow
  status public.catch_book_status NOT NULL DEFAULT 'offen',
  verification public.catch_book_verification,
  is_checked boolean NOT NULL DEFAULT false,
  is_submitted boolean NOT NULL DEFAULT false,
  submitted_at timestamptz,

  -- HejFish
  is_hejfish boolean NOT NULL DEFAULT false,
  is_empty boolean NOT NULL DEFAULT false,
  not_fished boolean NOT NULL DEFAULT false,

  remarks text,

  -- Meta
  created_by uuid REFERENCES auth.users(id) ON DELETE SET NULL,
  updated_by uuid REFERENCES auth.users(id) ON DELETE SET NULL,
  created_at timestamptz NOT NULL DEFAULT now(),
  updated_at timestamptz NOT NULL DEFAULT now(),

  UNIQUE(account_id, member_id, year)
);

CREATE INDEX ix_catch_books_account ON public.catch_books(account_id);
CREATE INDEX ix_catch_books_member ON public.catch_books(member_id);
CREATE INDEX ix_catch_books_year ON public.catch_books(account_id, year);
CREATE INDEX ix_catch_books_status ON public.catch_books(account_id, status);

ALTER TABLE public.catch_books ENABLE ROW LEVEL SECURITY;
REVOKE ALL ON public.catch_books FROM authenticated, service_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.catch_books TO authenticated;
GRANT ALL ON public.catch_books TO service_role;

CREATE POLICY catch_books_select ON public.catch_books FOR SELECT TO authenticated
  USING (public.has_role_on_account(account_id));
CREATE POLICY catch_books_insert ON public.catch_books FOR INSERT TO authenticated
  WITH CHECK (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));
CREATE POLICY catch_books_update ON public.catch_books FOR UPDATE TO authenticated
  USING (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));
CREATE POLICY catch_books_delete ON public.catch_books FOR DELETE TO authenticated
  USING (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));

CREATE TRIGGER trg_catch_books_updated_at
  BEFORE UPDATE ON public.catch_books
  FOR EACH ROW EXECUTE FUNCTION public.update_account_settings_timestamp();

-- =====================================================
-- 13. catches (ve_faenge)
-- =====================================================

CREATE TABLE IF NOT EXISTS public.catches (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  catch_book_id uuid NOT NULL REFERENCES public.catch_books(id) ON DELETE CASCADE,
  species_id uuid NOT NULL REFERENCES public.fish_species(id) ON DELETE RESTRICT,
  water_id uuid REFERENCES public.waters(id) ON DELETE SET NULL,
  member_id uuid REFERENCES public.members(id) ON DELETE SET NULL,

  catch_date date NOT NULL,
  quantity integer NOT NULL DEFAULT 1,
  length_cm numeric(5,1),
  weight_g numeric(8,0),

  -- Size category
  size_category public.fish_size_category,
  gender public.fish_gender,

  -- Flags
  is_empty_entry boolean NOT NULL DEFAULT false,
  has_error boolean NOT NULL DEFAULT false,

  -- HejFish
  hejfish_id text,

  -- Competition link
  competition_id uuid,
  competition_participant_id uuid,

  -- Permit
  permit_id uuid REFERENCES public.fishing_permits(id) ON DELETE SET NULL,

  remarks text,
  created_at timestamptz NOT NULL DEFAULT now()
);

-- K-factor computed: weight_g / (length_cm^3) * 100000
-- This is done application-side, not as a generated column, because
-- it requires both non-null values and the formula is specific to fisheries.

CREATE INDEX ix_catches_catch_book ON public.catches(catch_book_id);
CREATE INDEX ix_catches_species ON public.catches(species_id);
CREATE INDEX ix_catches_water ON public.catches(water_id);
CREATE INDEX ix_catches_member ON public.catches(member_id);
CREATE INDEX ix_catches_date ON public.catches(catch_date DESC);

ALTER TABLE public.catches ENABLE ROW LEVEL SECURITY;
REVOKE ALL ON public.catches FROM authenticated, service_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.catches TO authenticated;
GRANT ALL ON public.catches TO service_role;

CREATE POLICY catches_select ON public.catches FOR SELECT TO authenticated
  USING (EXISTS (SELECT 1 FROM public.catch_books cb WHERE cb.id = catches.catch_book_id AND public.has_role_on_account(cb.account_id)));
CREATE POLICY catches_mutate ON public.catches FOR ALL TO authenticated
  USING (EXISTS (SELECT 1 FROM public.catch_books cb WHERE cb.id = catches.catch_book_id AND public.has_permission(auth.uid(), cb.account_id, 'fischerei.write'::public.app_permissions)));

-- =====================================================
-- 14. water_inspectors (ve_kontrolleur_gewaesser)
-- =====================================================

CREATE TABLE IF NOT EXISTS public.water_inspectors (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
  water_id uuid NOT NULL REFERENCES public.waters(id) ON DELETE CASCADE,
  member_id uuid NOT NULL REFERENCES public.members(id) ON DELETE CASCADE,
  assignment_start date NOT NULL DEFAULT current_date,
  assignment_end date,
  created_at timestamptz NOT NULL DEFAULT now(),
  UNIQUE(water_id, member_id)
);

CREATE INDEX ix_water_inspectors_account ON public.water_inspectors(account_id);
CREATE INDEX ix_water_inspectors_water ON public.water_inspectors(water_id);
CREATE INDEX ix_water_inspectors_member ON public.water_inspectors(member_id);

ALTER TABLE public.water_inspectors ENABLE ROW LEVEL SECURITY;
REVOKE ALL ON public.water_inspectors FROM authenticated, service_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.water_inspectors TO authenticated;
GRANT ALL ON public.water_inspectors TO service_role;

CREATE POLICY water_inspectors_select ON public.water_inspectors FOR SELECT TO authenticated
  USING (public.has_role_on_account(account_id));
CREATE POLICY water_inspectors_mutate ON public.water_inspectors FOR ALL TO authenticated
  USING (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));

-- =====================================================
-- 15. competition_categories (ve_fanglisten_rubriken)
-- =====================================================

CREATE TABLE IF NOT EXISTS public.competition_categories (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
  name text NOT NULL,
  sort_order integer NOT NULL DEFAULT 0,
  created_at timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX ix_competition_categories_account ON public.competition_categories(account_id);
ALTER TABLE public.competition_categories ENABLE ROW LEVEL SECURITY;
REVOKE ALL ON public.competition_categories FROM authenticated, service_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.competition_categories TO authenticated;
GRANT ALL ON public.competition_categories TO service_role;

CREATE POLICY competition_categories_select ON public.competition_categories FOR SELECT TO authenticated
  USING (public.has_role_on_account(account_id));
CREATE POLICY competition_categories_mutate ON public.competition_categories FOR ALL TO authenticated
  USING (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));

-- =====================================================
-- 16. competitions (ve_fanglisten)
-- =====================================================

CREATE TABLE IF NOT EXISTS public.competitions (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
  event_id uuid REFERENCES public.events(id) ON DELETE SET NULL,
  name text NOT NULL,
  competition_date date NOT NULL,
  permit_id uuid REFERENCES public.fishing_permits(id) ON DELETE SET NULL,
  water_id uuid REFERENCES public.waters(id) ON DELETE SET NULL,
  max_participants integer,

  -- Scoring flags
  score_by_count boolean NOT NULL DEFAULT false,
  score_by_heaviest boolean NOT NULL DEFAULT false,
  score_by_total_weight boolean NOT NULL DEFAULT true,
  score_by_longest boolean NOT NULL DEFAULT false,
  score_by_total_length boolean NOT NULL DEFAULT false,

  -- Separation
  separate_member_guest_scoring boolean NOT NULL DEFAULT false,

  -- Result counts
  result_count_weight integer DEFAULT 3,
  result_count_length integer DEFAULT 3,
  result_count_count integer DEFAULT 3,

  -- Meta
  created_by uuid REFERENCES auth.users(id) ON DELETE SET NULL,
  created_at timestamptz NOT NULL DEFAULT now(),
  updated_at timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX ix_competitions_account ON public.competitions(account_id);
CREATE INDEX ix_competitions_date ON public.competitions(competition_date DESC);

ALTER TABLE public.competitions ENABLE ROW LEVEL SECURITY;
REVOKE ALL ON public.competitions FROM authenticated, service_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.competitions TO authenticated;
GRANT ALL ON public.competitions TO service_role;

CREATE POLICY competitions_select ON public.competitions FOR SELECT TO authenticated
  USING (public.has_role_on_account(account_id));
CREATE POLICY competitions_insert ON public.competitions FOR INSERT TO authenticated
  WITH CHECK (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));
CREATE POLICY competitions_update ON public.competitions FOR UPDATE TO authenticated
  USING (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));
CREATE POLICY competitions_delete ON public.competitions FOR DELETE TO authenticated
  USING (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));

CREATE TRIGGER trg_competitions_updated_at
  BEFORE UPDATE ON public.competitions
  FOR EACH ROW EXECUTE FUNCTION public.update_account_settings_timestamp();

-- =====================================================
-- 17. competition_participants (ve_fanglisten_teilnehmer)
-- =====================================================

CREATE TABLE IF NOT EXISTS public.competition_participants (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  competition_id uuid NOT NULL REFERENCES public.competitions(id) ON DELETE CASCADE,
  member_id uuid REFERENCES public.members(id) ON DELETE SET NULL,
  category_id uuid REFERENCES public.competition_categories(id) ON DELETE SET NULL,

  -- Guest/external participant info
  participant_name text NOT NULL,
  birth_date date,
  address text,
  phone text,
  email text,

  -- Status
  participated boolean NOT NULL DEFAULT false,

  -- Results (computed from catches)
  total_catch_count integer NOT NULL DEFAULT 0,
  total_weight_g integer NOT NULL DEFAULT 0,
  total_length_cm numeric(8,1) NOT NULL DEFAULT 0,
  heaviest_catch_g integer NOT NULL DEFAULT 0,
  longest_catch_cm numeric(5,1) NOT NULL DEFAULT 0,

  created_at timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX ix_competition_participants_competition ON public.competition_participants(competition_id);
CREATE INDEX ix_competition_participants_member ON public.competition_participants(member_id);

ALTER TABLE public.competition_participants ENABLE ROW LEVEL SECURITY;
REVOKE ALL ON public.competition_participants FROM authenticated, service_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.competition_participants TO authenticated;
GRANT ALL ON public.competition_participants TO service_role;

CREATE POLICY competition_participants_select ON public.competition_participants FOR SELECT TO authenticated
  USING (EXISTS (SELECT 1 FROM public.competitions c WHERE c.id = competition_participants.competition_id AND public.has_role_on_account(c.account_id)));
CREATE POLICY competition_participants_mutate ON public.competition_participants FOR ALL TO authenticated
  USING (EXISTS (SELECT 1 FROM public.competitions c WHERE c.id = competition_participants.competition_id AND public.has_permission(auth.uid(), c.account_id, 'fischerei.write'::public.app_permissions)));

-- Add FK from catches to competitions
ALTER TABLE public.catches
  ADD CONSTRAINT fk_catches_competition FOREIGN KEY (competition_id) REFERENCES public.competitions(id) ON DELETE SET NULL;
ALTER TABLE public.catches
  ADD CONSTRAINT fk_catches_competition_participant FOREIGN KEY (competition_participant_id) REFERENCES public.competition_participants(id) ON DELETE SET NULL;

-- =====================================================
-- 18. hejfish_sync (integration state tracking)
-- =====================================================

CREATE TABLE IF NOT EXISTS public.hejfish_sync (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
  entity_type text NOT NULL, -- 'water', 'species', 'member', 'catch'
  local_id uuid NOT NULL,
  hejfish_id text NOT NULL,
  last_synced_at timestamptz NOT NULL DEFAULT now(),
  sync_data jsonb,
  UNIQUE(account_id, entity_type, local_id)
);

CREATE INDEX ix_hejfish_sync_account ON public.hejfish_sync(account_id);
CREATE INDEX ix_hejfish_sync_entity ON public.hejfish_sync(entity_type, local_id);

ALTER TABLE public.hejfish_sync ENABLE ROW LEVEL SECURITY;
REVOKE ALL ON public.hejfish_sync FROM authenticated, service_role;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.hejfish_sync TO authenticated;
GRANT ALL ON public.hejfish_sync TO service_role;

CREATE POLICY hejfish_sync_select ON public.hejfish_sync FOR SELECT TO authenticated
  USING (public.has_role_on_account(account_id));
CREATE POLICY hejfish_sync_mutate ON public.hejfish_sync FOR ALL TO authenticated
  USING (public.has_permission(auth.uid(), account_id, 'fischerei.write'::public.app_permissions));

-- =====================================================
-- 19. Aggregate function for catch statistics
-- =====================================================

CREATE OR REPLACE FUNCTION public.get_catch_statistics(
  p_account_id uuid,
  p_year integer DEFAULT NULL,
  p_water_id uuid DEFAULT NULL
)
RETURNS TABLE(
  species_id uuid,
  species_name text,
  total_count bigint,
  total_weight_kg numeric,
  avg_length_cm numeric,
  avg_weight_g numeric,
  avg_k_factor numeric
)
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = ''
AS $$
BEGIN
  RETURN QUERY
  SELECT
    c.species_id,
    fs.name AS species_name,
    COUNT(*)::bigint AS total_count,
    ROUND(COALESCE(SUM(c.weight_g) / 1000.0, 0), 2) AS total_weight_kg,
    ROUND(AVG(c.length_cm), 1) AS avg_length_cm,
    ROUND(AVG(c.weight_g), 0) AS avg_weight_g,
    ROUND(AVG(
      CASE WHEN c.length_cm > 0 AND c.weight_g > 0
           THEN c.weight_g / POWER(c.length_cm, 3) * 100000
           ELSE NULL END
    ), 3) AS avg_k_factor
  FROM public.catches c
  JOIN public.catch_books cb ON cb.id = c.catch_book_id
  JOIN public.fish_species fs ON fs.id = c.species_id
  WHERE cb.account_id = p_account_id
    AND (p_year IS NULL OR cb.year = p_year)
    AND (p_water_id IS NULL OR c.water_id = p_water_id)
    AND c.is_empty_entry = false
  GROUP BY c.species_id, fs.name
  ORDER BY total_count DESC;
END;
$$;

GRANT EXECUTE ON FUNCTION public.get_catch_statistics(uuid, integer, uuid)
  TO authenticated, service_role;

-- =====================================================
-- 20. Function to compute lease amount for a given year
-- =====================================================

CREATE OR REPLACE FUNCTION public.compute_lease_amount(
  p_initial_amount numeric,
  p_fixed_increase numeric,
  p_percentage_increase numeric,
  p_start_year integer,
  p_target_year integer
)
RETURNS numeric
LANGUAGE plpgsql
IMMUTABLE
AS $$
DECLARE
  v_amount numeric;
  v_year_offset integer;
BEGIN
  v_year_offset := p_target_year - p_start_year;
  IF v_year_offset <= 0 THEN
    RETURN p_initial_amount;
  END IF;

  IF p_percentage_increase > 0 THEN
    v_amount := p_initial_amount * POWER(1 + p_percentage_increase / 100.0, v_year_offset);
  ELSE
    v_amount := p_initial_amount + (p_fixed_increase * v_year_offset);
  END IF;

  RETURN ROUND(v_amount, 2);
END;
$$;

GRANT EXECUTE ON FUNCTION public.compute_lease_amount(numeric, numeric, numeric, integer, integer)
  TO authenticated, service_role;
