-- HotelSync Database Schema
-- Migration 002 — Extended Schema

-- ── Hotels: дополнительные поля ────────────────────────────────────────────
ALTER TABLE hotels
  ADD COLUMN IF NOT EXISTS address       TEXT,
  ADD COLUMN IF NOT EXISTS phone         VARCHAR(50),
  ADD COLUMN IF NOT EXISTS email         VARCHAR(255),
  ADD COLUMN IF NOT EXISTS contact_person VARCHAR(255),
  ADD COLUMN IF NOT EXISTS logo_url      TEXT,
  ADD COLUMN IF NOT EXISTS check_in_time  TIME NOT NULL DEFAULT '14:00',
  ADD COLUMN IF NOT EXISTS check_out_time TIME NOT NULL DEFAULT '12:00',
  ADD COLUMN IF NOT EXISTS is_active     BOOLEAN NOT NULL DEFAULT true;

-- ── Room categories ─────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS room_categories (
  id          UUID         PRIMARY KEY DEFAULT gen_random_uuid(),
  hotel_id    UUID         NOT NULL REFERENCES hotels(id) ON DELETE CASCADE,
  name        VARCHAR(100) NOT NULL,
  description TEXT,
  color       VARCHAR(20)  NOT NULL DEFAULT '#6366f1',
  amenities   TEXT[]       NOT NULL DEFAULT '{}',
  sort_order  INTEGER      NOT NULL DEFAULT 99,
  created_at  TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
  updated_at  TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
  UNIQUE(hotel_id, name)
);

-- ── Rooms: дополнительные поля ──────────────────────────────────────────────
ALTER TABLE rooms
  ADD COLUMN IF NOT EXISTS name               VARCHAR(100),
  ADD COLUMN IF NOT EXISTS category_id        UUID REFERENCES room_categories(id) ON DELETE SET NULL,
  ADD COLUMN IF NOT EXISTS bed_type           VARCHAR(20) NOT NULL DEFAULT 'double'
                             CHECK (bed_type IN ('single','double','queen','king','twin')),
  ADD COLUMN IF NOT EXISTS beds               JSONB,
  ADD COLUMN IF NOT EXISTS housekeeping_status VARCHAR(20) NOT NULL DEFAULT 'clean'
                             CHECK (housekeeping_status IN ('clean','dirty','cleaning','inspect')),
  ADD COLUMN IF NOT EXISTS sort_order         INTEGER NOT NULL DEFAULT 99,
  ADD COLUMN IF NOT EXISTS allow_hourly       BOOLEAN NOT NULL DEFAULT false,
  ADD COLUMN IF NOT EXISTS hourly_rate        DECIMAL(10,2),
  ADD COLUMN IF NOT EXISTS extra_place        JSONB,
  ADD COLUMN IF NOT EXISTS child_policy       JSONB,
  ADD COLUMN IF NOT EXISTS description        TEXT,
  ADD COLUMN IF NOT EXISTS photos             TEXT[]   NOT NULL DEFAULT '{}';

-- Переименуем старые поля для единообразия
ALTER TABLE rooms RENAME COLUMN IF EXISTS capacity       TO max_guests;
ALTER TABLE rooms RENAME COLUMN IF EXISTS price_per_night TO base_rate;

-- ── Guests (база гостей) ────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS guests (
  id            UUID         PRIMARY KEY DEFAULT gen_random_uuid(),
  hotel_id      UUID         NOT NULL REFERENCES hotels(id) ON DELETE CASCADE,
  first_name    VARCHAR(100) NOT NULL,
  last_name     VARCHAR(100) NOT NULL,
  email         VARCHAR(255),
  phone         VARCHAR(50),
  passport      VARCHAR(100),
  birth_date    DATE,
  nationality   VARCHAR(50),
  gender        VARCHAR(10)  CHECK (gender IN ('male','female','other')),
  city          VARCHAR(100),
  notes         TEXT,
  tags          TEXT[]       NOT NULL DEFAULT '{}',
  loyalty_points INTEGER     NOT NULL DEFAULT 0,
  loyalty_tier  VARCHAR(20)  NOT NULL DEFAULT 'standard'
                  CHECK (loyalty_tier IN ('standard','silver','gold','platinum')),
  total_stays   INTEGER      NOT NULL DEFAULT 0,
  total_spent   DECIMAL(12,2) NOT NULL DEFAULT 0,
  created_at    TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
  updated_at    TIMESTAMPTZ  NOT NULL DEFAULT NOW()
);

-- ── Bookings: дополнительные поля ──────────────────────────────────────────
ALTER TABLE bookings
  ADD COLUMN IF NOT EXISTS guest_id       UUID REFERENCES guests(id) ON DELETE SET NULL,
  ADD COLUMN IF NOT EXISTS booking_number VARCHAR(20),
  ADD COLUMN IF NOT EXISTS inquiry_status VARCHAR(20) NOT NULL DEFAULT 'confirmed'
                             CHECK (inquiry_status IN ('inquiry','confirmed','checked_in','checked_out','cancelled','no_show')),
  ADD COLUMN IF NOT EXISTS payment_status VARCHAR(20) NOT NULL DEFAULT 'pending'
                             CHECK (payment_status IN ('pending','partial','paid','refunded')),
  ADD COLUMN IF NOT EXISTS extra_adults   INTEGER NOT NULL DEFAULT 0,
  ADD COLUMN IF NOT EXISTS extra_children INTEGER NOT NULL DEFAULT 0,
  ADD COLUMN IF NOT EXISTS extra_place_fee DECIMAL(10,2) NOT NULL DEFAULT 0,
  ADD COLUMN IF NOT EXISTS meal_plan      VARCHAR(20)
                             CHECK (meal_plan IN ('none','breakfast','half_board','full_board','all_inclusive')),
  ADD COLUMN IF NOT EXISTS early_checkin  BOOLEAN NOT NULL DEFAULT false,
  ADD COLUMN IF NOT EXISTS late_checkout  BOOLEAN NOT NULL DEFAULT false,
  ADD COLUMN IF NOT EXISTS confirmed_at   TIMESTAMPTZ,
  ADD COLUMN IF NOT EXISTS checked_in_at  TIMESTAMPTZ,
  ADD COLUMN IF NOT EXISTS checked_out_at TIMESTAMPTZ;

-- ── Tariffs ─────────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS tariffs (
  id           UUID          PRIMARY KEY DEFAULT gen_random_uuid(),
  hotel_id     UUID          NOT NULL REFERENCES hotels(id) ON DELETE CASCADE,
  name         VARCHAR(100)  NOT NULL,
  description  TEXT,
  type         VARCHAR(20)   NOT NULL DEFAULT 'percent'
                 CHECK (type IN ('percent','fixed','multiplier')),
  value        DECIMAL(10,2) NOT NULL DEFAULT 0,
  is_active    BOOLEAN       NOT NULL DEFAULT true,
  applies_to   VARCHAR(20)   NOT NULL DEFAULT 'all'
                 CHECK (applies_to IN ('all','weekdays','weekends','specific')),
  days_of_week INTEGER[]     NOT NULL DEFAULT '{}',
  date_from    DATE,
  date_to      DATE,
  min_nights   INTEGER,
  sort_order   INTEGER       NOT NULL DEFAULT 99,
  created_at   TIMESTAMPTZ   NOT NULL DEFAULT NOW(),
  updated_at   TIMESTAMPTZ   NOT NULL DEFAULT NOW()
);

-- ── Discounts ───────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS discounts (
  id            UUID          PRIMARY KEY DEFAULT gen_random_uuid(),
  hotel_id      UUID          NOT NULL REFERENCES hotels(id) ON DELETE CASCADE,
  name          VARCHAR(100)  NOT NULL,
  description   TEXT,
  type          VARCHAR(20)   NOT NULL DEFAULT 'percent'
                  CHECK (type IN ('percent','fixed')),
  value         DECIMAL(10,2) NOT NULL,
  code          VARCHAR(50),
  is_active     BOOLEAN       NOT NULL DEFAULT true,
  date_from     DATE,
  date_to       DATE,
  min_nights    INTEGER,
  min_guests    INTEGER,
  usage_limit   INTEGER,
  usage_count   INTEGER       NOT NULL DEFAULT 0,
  created_at    TIMESTAMPTZ   NOT NULL DEFAULT NOW(),
  updated_at    TIMESTAMPTZ   NOT NULL DEFAULT NOW()
);

-- ── Loyalty rules ───────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS loyalty_rules (
  id          UUID          PRIMARY KEY DEFAULT gen_random_uuid(),
  hotel_id    UUID          NOT NULL REFERENCES hotels(id) ON DELETE CASCADE,
  name        VARCHAR(100)  NOT NULL,
  event       VARCHAR(30)   NOT NULL
                CHECK (event IN ('stay','review','birthday','referral','manual')),
  points      INTEGER       NOT NULL DEFAULT 0,
  is_active   BOOLEAN       NOT NULL DEFAULT true,
  created_at  TIMESTAMPTZ   NOT NULL DEFAULT NOW(),
  updated_at  TIMESTAMPTZ   NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS loyalty_tiers (
  id              UUID    PRIMARY KEY DEFAULT gen_random_uuid(),
  hotel_id        UUID    NOT NULL REFERENCES hotels(id) ON DELETE CASCADE,
  name            VARCHAR(50)   NOT NULL,
  tier            VARCHAR(20)   NOT NULL
                    CHECK (tier IN ('standard','silver','gold','platinum')),
  min_points      INTEGER NOT NULL DEFAULT 0,
  discount_percent DECIMAL(5,2) NOT NULL DEFAULT 0,
  created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  UNIQUE(hotel_id, tier)
);

-- ── Reviews ─────────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS reviews (
  id          UUID         PRIMARY KEY DEFAULT gen_random_uuid(),
  hotel_id    UUID         NOT NULL REFERENCES hotels(id) ON DELETE CASCADE,
  booking_id  UUID         REFERENCES bookings(id) ON DELETE SET NULL,
  guest_id    UUID         REFERENCES guests(id) ON DELETE SET NULL,
  guest_name  VARCHAR(255) NOT NULL,
  source      VARCHAR(20)  NOT NULL DEFAULT 'direct'
                CHECK (source IN ('direct','booking_com','airbnb','google','tripadvisor')),
  rating      SMALLINT     NOT NULL CHECK (rating BETWEEN 1 AND 5),
  text        TEXT,
  reply       TEXT,
  replied_at  TIMESTAMPTZ,
  is_public   BOOLEAN      NOT NULL DEFAULT true,
  created_at  TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
  updated_at  TIMESTAMPTZ  NOT NULL DEFAULT NOW()
);

-- ── Maintenance tasks ───────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS maintenance_tasks (
  id           UUID         PRIMARY KEY DEFAULT gen_random_uuid(),
  hotel_id     UUID         NOT NULL REFERENCES hotels(id) ON DELETE CASCADE,
  room_id      UUID         REFERENCES rooms(id) ON DELETE SET NULL,
  title        VARCHAR(255) NOT NULL,
  description  TEXT,
  category     VARCHAR(30)  NOT NULL DEFAULT 'other'
                 CHECK (category IN ('plumbing','electrical','furniture','hvac','exterior','other')),
  priority     VARCHAR(10)  NOT NULL DEFAULT 'medium'
                 CHECK (priority IN ('low','medium','high','urgent')),
  status       VARCHAR(20)  NOT NULL DEFAULT 'open'
                 CHECK (status IN ('open','in_progress','done','cancelled')),
  assignee_id  UUID         REFERENCES users(id) ON DELETE SET NULL,
  cost         DECIMAL(10,2),
  due_date     DATE,
  completed_at TIMESTAMPTZ,
  created_at   TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
  updated_at   TIMESTAMPTZ  NOT NULL DEFAULT NOW()
);

-- ── POS: категории, позиции, заказы ────────────────────────────────────────
CREATE TABLE IF NOT EXISTS pos_categories (
  id         UUID        PRIMARY KEY DEFAULT gen_random_uuid(),
  hotel_id   UUID        NOT NULL REFERENCES hotels(id) ON DELETE CASCADE,
  name       VARCHAR(100) NOT NULL,
  sort_order INTEGER     NOT NULL DEFAULT 99,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS pos_items (
  id          UUID          PRIMARY KEY DEFAULT gen_random_uuid(),
  hotel_id    UUID          NOT NULL REFERENCES hotels(id) ON DELETE CASCADE,
  category_id UUID          REFERENCES pos_categories(id) ON DELETE SET NULL,
  name        VARCHAR(255)  NOT NULL,
  price       DECIMAL(10,2) NOT NULL,
  vat_rate    SMALLINT      NOT NULL DEFAULT 20,
  is_active   BOOLEAN       NOT NULL DEFAULT true,
  sort_order  INTEGER       NOT NULL DEFAULT 99,
  created_at  TIMESTAMPTZ   NOT NULL DEFAULT NOW(),
  updated_at  TIMESTAMPTZ   NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS pos_orders (
  id           UUID          PRIMARY KEY DEFAULT gen_random_uuid(),
  hotel_id     UUID          NOT NULL REFERENCES hotels(id) ON DELETE CASCADE,
  room_id      UUID          REFERENCES rooms(id) ON DELETE SET NULL,
  booking_id   UUID          REFERENCES bookings(id) ON DELETE SET NULL,
  operator_id  UUID          REFERENCES users(id) ON DELETE SET NULL,
  items        JSONB         NOT NULL DEFAULT '[]',
  subtotal     DECIMAL(10,2) NOT NULL DEFAULT 0,
  discount     DECIMAL(10,2) NOT NULL DEFAULT 0,
  total        DECIMAL(10,2) NOT NULL DEFAULT 0,
  payment_type VARCHAR(20)   NOT NULL DEFAULT 'cash'
                 CHECK (payment_type IN ('cash','card','room_charge','online')),
  status       VARCHAR(20)   NOT NULL DEFAULT 'open'
                 CHECK (status IN ('open','paid','cancelled','refunded')),
  fiscal_receipt_id VARCHAR(100),
  created_at   TIMESTAMPTZ   NOT NULL DEFAULT NOW(),
  updated_at   TIMESTAMPTZ   NOT NULL DEFAULT NOW()
);

-- ── Document templates ──────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS document_templates (
  id         UUID         PRIMARY KEY DEFAULT gen_random_uuid(),
  hotel_id   UUID         NOT NULL REFERENCES hotels(id) ON DELETE CASCADE,
  name       VARCHAR(255) NOT NULL,
  type       VARCHAR(30)  NOT NULL
               CHECK (type IN ('registration_card','invoice','act','contract','other')),
  content    TEXT         NOT NULL DEFAULT '',
  is_default BOOLEAN      NOT NULL DEFAULT false,
  created_at TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ  NOT NULL DEFAULT NOW()
);

-- ── Hotel settings (key-value для гибких настроек) ──────────────────────────
CREATE TABLE IF NOT EXISTS hotel_settings (
  hotel_id   UUID         NOT NULL REFERENCES hotels(id) ON DELETE CASCADE,
  key        VARCHAR(100) NOT NULL,
  value      JSONB        NOT NULL DEFAULT 'null',
  updated_at TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
  PRIMARY KEY (hotel_id, key)
);

-- ── Indexes ──────────────────────────────────────────────────────────────────
CREATE INDEX IF NOT EXISTS idx_guests_hotel         ON guests(hotel_id);
CREATE INDEX IF NOT EXISTS idx_guests_email         ON guests(email);
CREATE INDEX IF NOT EXISTS idx_bookings_guest       ON bookings(guest_id);
CREATE INDEX IF NOT EXISTS idx_bookings_number      ON bookings(booking_number);
CREATE INDEX IF NOT EXISTS idx_tariffs_hotel        ON tariffs(hotel_id);
CREATE INDEX IF NOT EXISTS idx_discounts_hotel      ON discounts(hotel_id);
CREATE INDEX IF NOT EXISTS idx_reviews_hotel        ON reviews(hotel_id);
CREATE INDEX IF NOT EXISTS idx_maintenance_hotel    ON maintenance_tasks(hotel_id);
CREATE INDEX IF NOT EXISTS idx_pos_orders_hotel     ON pos_orders(hotel_id);
CREATE INDEX IF NOT EXISTS idx_room_categories_hotel ON room_categories(hotel_id);
CREATE INDEX IF NOT EXISTS idx_rooms_category       ON rooms(category_id);
