-- 启用 PostGIS 扩展
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS postgis;

-- 枚举类型
CREATE TYPE artifact_category AS ENUM (
  'bronze','painting_calligraphy','porcelain','jade','gold_silver',
  'lacquer','textile','stone_carving','wood_carving','dunhuang','ancient_book','other'
);
CREATE TYPE artifact_level AS ENUM ('level_1','level_2','level_3','general','unknown');
CREATE TYPE artifact_status AS ENUM ('at_home','away','in_transit','unknown');
CREATE TYPE location_type AS ENUM ('domestic','overseas','unknown','in_transit');
CREATE TYPE location_precision AS ENUM ('exact_room','exact_building','city','country','region');
CREATE TYPE display_status AS ENUM ('on_display','in_storage','loaned','repairing','touring','unknown');
CREATE TYPE source_type AS ENUM ('institution_feed','manual_entry','user_report','expert_verify','public_source');
CREATE TYPE publish_status AS ENUM ('draft','pending','published','archived','rejected');
CREATE TYPE tag_value_type AS ENUM ('single','multiple','boolean','text','number');

-- users
CREATE TABLE users (
  id            UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  username      VARCHAR(100) UNIQUE,
  phone         VARCHAR(30),
  email         VARCHAR(255),
  password_hash VARCHAR(255),
  nickname      VARCHAR(100),
  avatar_url    TEXT,
  user_type     VARCHAR(30) NOT NULL DEFAULT 'public',
  institution_id UUID,
  is_active     BOOLEAN NOT NULL DEFAULT TRUE,
  created_at    TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at    TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- roles
CREATE TABLE roles (
  id          UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  code        VARCHAR(50) UNIQUE NOT NULL,
  name        VARCHAR(100) NOT NULL,
  description TEXT,
  created_at  TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- permissions
CREATE TABLE permissions (
  id         UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  code       VARCHAR(100) UNIQUE NOT NULL,
  name       VARCHAR(100) NOT NULL,
  module     VARCHAR(50) NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- user_roles
CREATE TABLE user_roles (
  user_id    UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  role_id    UUID NOT NULL REFERENCES roles(id) ON DELETE CASCADE,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  PRIMARY KEY (user_id, role_id)
);

-- institutions
CREATE TABLE institutions (
  id               UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  name             VARCHAR(255) NOT NULL,
  short_name       VARCHAR(100),
  code             VARCHAR(100) UNIQUE,
  institution_type VARCHAR(50) NOT NULL DEFAULT 'museum',
  country          VARCHAR(100) NOT NULL DEFAULT '中国',
  province         VARCHAR(100),
  city             VARCHAR(100),
  address          TEXT,
  location         geography(Point, 4326),
  official_website TEXT,
  description      TEXT,
  is_verified      BOOLEAN NOT NULL DEFAULT FALSE,
  publish_status   publish_status NOT NULL DEFAULT 'draft',
  created_at       TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at       TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_institutions_location_gist ON institutions USING GIST(location);
CREATE INDEX idx_institutions_name ON institutions(name);
CREATE INDEX idx_institutions_country_city ON institutions(country, city);

-- artifacts
CREATE TABLE artifacts (
  id                 UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  unified_map_id     VARCHAR(50) UNIQUE,
  name               VARCHAR(255) NOT NULL,
  alternative_names  TEXT[] DEFAULT '{}',
  category           artifact_category NOT NULL DEFAULT 'other',
  dynasty            VARCHAR(100),
  level              artifact_level NOT NULL DEFAULT 'unknown',
  material           VARCHAR(255),
  dimensions         VARCHAR(255),
  current_status     artifact_status NOT NULL DEFAULT 'unknown',
  home_institution_id UUID REFERENCES institutions(id),
  summary            TEXT,
  story_hook         VARCHAR(255),
  persona_quote      VARCHAR(255),
  publish_status     publish_status NOT NULL DEFAULT 'draft',
  created_by         UUID REFERENCES users(id),
  updated_by         UUID REFERENCES users(id),
  created_at         TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at         TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_artifacts_name ON artifacts(name);
CREATE INDEX idx_artifacts_category ON artifacts(category);
CREATE INDEX idx_artifacts_dynasty ON artifacts(dynasty);
CREATE INDEX idx_artifacts_status ON artifacts(current_status);
CREATE INDEX idx_artifacts_home_institution ON artifacts(home_institution_id);
CREATE INDEX idx_artifacts_publish_status ON artifacts(publish_status);

-- artifact_locations
CREATE TABLE artifact_locations (
  id                  UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  artifact_id         UUID NOT NULL REFERENCES artifacts(id) ON DELETE CASCADE,
  location_type       location_type NOT NULL DEFAULT 'unknown',
  institution_id      UUID REFERENCES institutions(id),
  precise_location    geography(Point, 4326),
  public_location     geography(Point, 4326),
  fuzzy_area          geography(Polygon, 4326),
  precision           location_precision NOT NULL DEFAULT 'city',
  floor_plan_ref      VARCHAR(255),
  room_name           VARCHAR(255),
  cabinet_no          VARCHAR(100),
  display_status      display_status NOT NULL DEFAULT 'unknown',
  source_type         source_type NOT NULL DEFAULT 'manual_entry',
  source_description  TEXT,
  discoverer_user_id  UUID REFERENCES users(id),
  is_current          BOOLEAN NOT NULL DEFAULT FALSE,
  verified_at         TIMESTAMPTZ,
  valid_from          TIMESTAMPTZ,
  valid_until         TIMESTAMPTZ,
  created_by          UUID REFERENCES users(id),
  created_at          TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at          TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_artifact_locations_artifact_id ON artifact_locations(artifact_id);
CREATE INDEX idx_artifact_locations_institution_id ON artifact_locations(institution_id);
CREATE INDEX idx_artifact_locations_public_location_gist ON artifact_locations USING GIST(public_location);
CREATE INDEX idx_artifact_locations_precise_location_gist ON artifact_locations USING GIST(precise_location);
CREATE INDEX idx_artifact_locations_fuzzy_area_gist ON artifact_locations USING GIST(fuzzy_area);
CREATE INDEX idx_artifact_locations_current ON artifact_locations(artifact_id, is_current);

-- tag_categories
CREATE TABLE tag_categories (
  id          UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  code        VARCHAR(100) UNIQUE NOT NULL,
  name        VARCHAR(100) NOT NULL,
  description TEXT,
  sort_order  INT NOT NULL DEFAULT 0,
  is_system   BOOLEAN NOT NULL DEFAULT FALSE,
  created_at  TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- tags
CREATE TABLE tags (
  id          UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  category_id UUID NOT NULL REFERENCES tag_categories(id),
  code        VARCHAR(100) UNIQUE NOT NULL,
  name        VARCHAR(100) NOT NULL,
  value_type  tag_value_type NOT NULL DEFAULT 'single',
  description TEXT,
  color       VARCHAR(20),
  icon        VARCHAR(100),
  is_system   BOOLEAN NOT NULL DEFAULT FALSE,
  is_active   BOOLEAN NOT NULL DEFAULT TRUE,
  sort_order  INT NOT NULL DEFAULT 0,
  created_at  TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at  TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- artifact_tags
CREATE TABLE artifact_tags (
  id            UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  artifact_id   UUID NOT NULL REFERENCES artifacts(id) ON DELETE CASCADE,
  tag_id        UUID NOT NULL REFERENCES tags(id),
  value_text    TEXT,
  value_number  NUMERIC,
  confidence    NUMERIC(5,2),
  source_type   source_type NOT NULL DEFAULT 'manual_entry',
  review_status VARCHAR(30) NOT NULL DEFAULT 'approved',
  created_by    UUID REFERENCES users(id),
  created_at    TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE UNIQUE INDEX idx_artifact_tags_unique ON artifact_tags(artifact_id, tag_id, COALESCE(value_text, ''));
CREATE INDEX idx_artifact_tags_artifact_id ON artifact_tags(artifact_id);
CREATE INDEX idx_artifact_tags_tag_id ON artifact_tags(tag_id);

-- digital_assets
CREATE TABLE digital_assets (
  id               UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  artifact_id      UUID REFERENCES artifacts(id) ON DELETE CASCADE,
  institution_id   UUID REFERENCES institutions(id),
  asset_type       VARCHAR(50) NOT NULL DEFAULT 'image',
  title            VARCHAR(255),
  url              TEXT NOT NULL,
  thumbnail_url    TEXT,
  mime_type        VARCHAR(100),
  size_bytes       BIGINT,
  copyright_owner  VARCHAR(255),
  license_scope    TEXT,
  sort_order       INT NOT NULL DEFAULT 0,
  created_by       UUID REFERENCES users(id),
  created_at       TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_digital_assets_artifact_id ON digital_assets(artifact_id);

-- operation_logs
CREATE TABLE operation_logs (
  id             UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  operator_id    UUID REFERENCES users(id),
  operator_role  VARCHAR(50),
  action         VARCHAR(100) NOT NULL,
  target_type    VARCHAR(100) NOT NULL,
  target_id      UUID,
  before_data    JSONB,
  after_data     JSONB,
  ip_address     VARCHAR(50),
  user_agent     TEXT,
  created_at     TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_operation_logs_operator_id ON operation_logs(operator_id);
CREATE INDEX idx_operation_logs_target ON operation_logs(target_type, target_id);
CREATE INDEX idx_operation_logs_created_at ON operation_logs(created_at DESC);
