CREATE TABLE IF NOT EXISTS environments (
  id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  name text NOT NULL UNIQUE
);

CREATE TABLE IF NOT EXISTS skills (
  id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  name text NOT NULL,
  subcategory text,
  UNIQUE (name, subcategory)
);

CREATE TABLE IF NOT EXISTS favorite_things (
  id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  name text NOT NULL UNIQUE
);

CREATE TABLE IF NOT EXISTS pokemon (
  id integer PRIMARY KEY,
  name text NOT NULL UNIQUE,
  environment_id integer NOT NULL REFERENCES environments(id)
);

CREATE TABLE IF NOT EXISTS pokemon_skills (
  pokemon_id integer NOT NULL REFERENCES pokemon(id) ON DELETE CASCADE,
  skill_id integer NOT NULL REFERENCES skills(id),
  PRIMARY KEY (pokemon_id, skill_id)
);

CREATE TABLE IF NOT EXISTS pokemon_favorite_things (
  pokemon_id integer NOT NULL REFERENCES pokemon(id) ON DELETE CASCADE,
  favorite_thing_id integer NOT NULL REFERENCES favorite_things(id),
  PRIMARY KEY (pokemon_id, favorite_thing_id)
);

CREATE TABLE IF NOT EXISTS item_categories (
  id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  name text NOT NULL UNIQUE
);

CREATE TABLE IF NOT EXISTS item_usages (
  id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  name text NOT NULL UNIQUE
);

CREATE TABLE IF NOT EXISTS acquisition_methods (
  id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  name text NOT NULL UNIQUE
);

CREATE TABLE IF NOT EXISTS recipes (
  id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  name text NOT NULL UNIQUE
);

CREATE TABLE IF NOT EXISTS recipe_acquisition_methods (
  recipe_id integer NOT NULL REFERENCES recipes(id) ON DELETE CASCADE,
  acquisition_method_id integer NOT NULL REFERENCES acquisition_methods(id),
  PRIMARY KEY (recipe_id, acquisition_method_id)
);

CREATE TABLE IF NOT EXISTS items (
  id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  name text NOT NULL UNIQUE,
  category_id integer NOT NULL REFERENCES item_categories(id),
  usage_id integer REFERENCES item_usages(id),
  recipe_id integer REFERENCES recipes(id),
  dyeable boolean NOT NULL DEFAULT false,
  dual_dyeable boolean NOT NULL DEFAULT false,
  pattern_editable boolean NOT NULL DEFAULT false
);

ALTER TABLE items ALTER COLUMN usage_id DROP NOT NULL;

DROP TABLE IF EXISTS item_item_tags;
DROP TABLE IF EXISTS item_tags;

CREATE TABLE IF NOT EXISTS item_acquisition_methods (
  item_id integer NOT NULL REFERENCES items(id) ON DELETE CASCADE,
  acquisition_method_id integer NOT NULL REFERENCES acquisition_methods(id),
  PRIMARY KEY (item_id, acquisition_method_id)
);

CREATE TABLE IF NOT EXISTS item_favorite_things (
  item_id integer NOT NULL REFERENCES items(id) ON DELETE CASCADE,
  favorite_thing_id integer NOT NULL REFERENCES favorite_things(id),
  PRIMARY KEY (item_id, favorite_thing_id)
);

CREATE TABLE IF NOT EXISTS recipe_materials (
  recipe_id integer NOT NULL REFERENCES recipes(id) ON DELETE CASCADE,
  item_id integer NOT NULL REFERENCES items(id),
  quantity integer NOT NULL CHECK (quantity > 0),
  PRIMARY KEY (recipe_id, item_id)
);

CREATE TABLE IF NOT EXISTS maps (
  id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  name text NOT NULL UNIQUE
);

CREATE TABLE IF NOT EXISTS habitats (
  id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  name text NOT NULL UNIQUE
);

CREATE TABLE IF NOT EXISTS habitat_recipe_items (
  habitat_id integer NOT NULL REFERENCES habitats(id) ON DELETE CASCADE,
  item_id integer NOT NULL REFERENCES items(id),
  quantity integer NOT NULL CHECK (quantity > 0),
  PRIMARY KEY (habitat_id, item_id)
);

CREATE TABLE IF NOT EXISTS habitat_pokemon (
  habitat_id integer NOT NULL REFERENCES habitats(id) ON DELETE CASCADE,
  pokemon_id integer NOT NULL REFERENCES pokemon(id) ON DELETE CASCADE,
  map_id integer NOT NULL REFERENCES maps(id),
  time_of_day text NOT NULL CHECK (time_of_day IN ('早晨', '中午', '傍晚', '晚上')),
  weather text NOT NULL CHECK (weather IN ('晴天', '阴天', '雨天')),
  rarity integer NOT NULL CHECK (rarity BETWEEN 1 AND 3),
  PRIMARY KEY (habitat_id, pokemon_id, map_id, time_of_day, weather)
);
