-- Создание базы данных (выполните один раз под суперпользователем postgres):
-- CREATE DATABASE mkd_control_center WITH ENCODING 'UTF8';

-- Далее подключитесь к базе mkd_control_center и выполните это тело файла.

-- ========= УЧАСТКИ =========
CREATE TABLE IF NOT EXISTS districts (
  id           VARCHAR(50) PRIMARY KEY,
  name         TEXT NOT NULL,
  manager_name TEXT NOT NULL
);

-- ========= ДОМА =========
-- Для упрощения: вся структура Building хранится в одном JSONB-поле data.
CREATE TABLE IF NOT EXISTS buildings (
  id    VARCHAR(50) PRIMARY KEY,
  data  JSONB NOT NULL
);

-- ========= ЗАЯВКИ =========
CREATE TYPE doma_application_status AS ENUM ('new', 'in_progress', 'deferred', 'done', 'canceled');

CREATE TABLE IF NOT EXISTS applications (
  id             BIGSERIAL PRIMARY KEY,
  number         TEXT NOT NULL,
  status         doma_application_status NOT NULL,
  description    TEXT NOT NULL,
  address        TEXT NOT NULL,
  apartment      TEXT NOT NULL,
  client_name    TEXT NOT NULL,
  created_at     TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  deadline_at    TIMESTAMPTZ NOT NULL,
  performer_name TEXT,
  employee_id    VARCHAR(50) REFERENCES employees(id) ON DELETE SET NULL,
  building_id    VARCHAR(50) REFERENCES buildings(id) ON DELETE SET NULL,
  is_overdue     BOOLEAN NOT NULL DEFAULT FALSE,
  updated_at     TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_applications_building ON applications(building_id);
CREATE INDEX IF NOT EXISTS idx_applications_employee ON applications(employee_id);
CREATE INDEX IF NOT EXISTS idx_applications_performer ON applications(performer_name);
CREATE INDEX IF NOT EXISTS idx_applications_status ON applications(status);
CREATE INDEX IF NOT EXISTS idx_applications_overdue ON applications(is_overdue);
CREATE INDEX IF NOT EXISTS idx_applications_deadline ON applications(deadline_at);

-- ========= ТЕСТОВЫЕ ДАННЫЕ =========
-- Демо данные удалены. Создавайте участки и дома через интерфейс приложения.

-- INSERT INTO districts (id, name, manager_name) VALUES
--   ('d-1', 'Участок №1 (Центральный)', 'Смирнов А.В.'),
--   ('d-2', 'Участок №2 (Заречный)', 'Петров Б.Г.')
-- ON CONFLICT (id) DO NOTHING;

-- INSERT INTO buildings (id, data) VALUES ...
-- ON CONFLICT (id) DO NOTHING;

-- INSERT INTO applications (number, status, description, address, apartment, client_name, created_at, deadline_at, performer_name)
-- VALUES ...
-- ON CONFLICT DO NOTHING;

-- ========= ФИНАНСОВЫЕ ДАННЫЕ ИЗ 1С =========

-- Настройки маппинга колонок CSV/XLSX (создаем первой, т.к. на неё ссылается financial_reports)
CREATE TABLE IF NOT EXISTS financial_report_mappings (
  id                BIGSERIAL PRIMARY KEY,
  name              TEXT NOT NULL,
  description       TEXT,
  is_default        BOOLEAN DEFAULT FALSE,
  column_mappings   JSONB NOT NULL, -- { "source_column": "target_field", ... }
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Метаданные загруженных отчетов
CREATE TABLE IF NOT EXISTS financial_reports (
  id                BIGSERIAL PRIMARY KEY,
  filename           TEXT NOT NULL,
  file_type          VARCHAR(10) NOT NULL CHECK (file_type IN ('CSV', 'XLSX')),
  uploaded_at       TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  uploaded_by       TEXT,
  status            VARCHAR(20) NOT NULL DEFAULT 'processing' CHECK (status IN ('processing', 'completed', 'failed', 'partial')),
  total_rows        INTEGER,
  processed_rows    INTEGER DEFAULT 0,
  error_rows        INTEGER DEFAULT 0,
  error_log         JSONB,
  mapping_id        BIGINT REFERENCES financial_report_mappings(id) ON DELETE SET NULL
);

-- Финансовые данные по домам
CREATE TABLE IF NOT EXISTS building_financial_data (
  id                BIGSERIAL PRIMARY KEY,
  building_id       VARCHAR(50) NOT NULL REFERENCES buildings(id) ON DELETE CASCADE,
  report_id         BIGINT REFERENCES financial_reports(id) ON DELETE SET NULL,
  period_start      DATE NOT NULL,
  period_end        DATE NOT NULL,
  period_type       VARCHAR(10) NOT NULL CHECK (period_type IN ('month', 'quarter', 'year')),
  -- Доходы
  total_income      NUMERIC(15, 2) DEFAULT 0,
  income_by_items   JSONB, -- { "item_name": amount, ... }
  -- Расходы
  total_expenses    NUMERIC(15, 2) DEFAULT 0,
  expenses_by_items JSONB, -- { "item_name": amount, ... }
  -- Баланс
  balance           NUMERIC(15, 2) DEFAULT 0,
  -- Дополнительные данные
  metadata          JSONB,
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  UNIQUE(building_id, period_start, period_end, period_type)
);

CREATE INDEX IF NOT EXISTS idx_building_financial_data_building ON building_financial_data(building_id);
CREATE INDEX IF NOT EXISTS idx_building_financial_data_period ON building_financial_data(period_start, period_end);
CREATE INDEX IF NOT EXISTS idx_building_financial_data_report ON building_financial_data(report_id);

-- ========= ОФИС: ЗАЯВКИ НА РЕМОНТ ТЕХНИКИ =========

CREATE TYPE office_equipment_type AS ENUM ('pc', 'laptop', 'air_conditioner', 'printer', 'other');
CREATE TYPE repair_request_status AS ENUM (
  'new',
  'search_contractor',      -- Поиск подрядчика
  'agreed_with_contractor', -- Договорились с подрядчиком
  'waiting_delivery',       -- Ожидание поставки
  'taken_for_repair',       -- Увезли на ремонт
  'self_repair',            -- Ремонт самостоятельно
  'in_progress',            -- В работе
  'completed',              -- Выполнена
  'canceled'                -- Отменена
);

-- Справочник оборудования
CREATE TABLE IF NOT EXISTS office_equipment (
  id                BIGSERIAL PRIMARY KEY,
  name              TEXT NOT NULL,
  type              office_equipment_type NOT NULL,
  brand             TEXT,
  model             TEXT,
  serial_number     TEXT UNIQUE,
  assigned_to       TEXT, -- Имя сотрудника
  purchase_date     DATE,
  warranty_until    DATE,
  next_maintenance_date DATE, -- Дата следующего ТО
  condition         VARCHAR(20) NOT NULL DEFAULT 'good' CHECK (condition IN ('good', 'fair', 'poor')),
  notes             TEXT,
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Заявки на ремонт
CREATE TABLE IF NOT EXISTS office_repair_requests (
  id                BIGSERIAL PRIMARY KEY,
  equipment_id      BIGINT NOT NULL REFERENCES office_equipment(id) ON DELETE CASCADE,
  requester_name    TEXT NOT NULL,
  description       TEXT NOT NULL,
  priority          VARCHAR(10) NOT NULL DEFAULT 'medium' CHECK (priority IN ('low', 'medium', 'high', 'urgent')),
  status            repair_request_status NOT NULL DEFAULT 'new',
  assigned_to       TEXT, -- Исполнитель
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  started_at        TIMESTAMPTZ,
  completed_at      TIMESTAMPTZ,
  canceled_at       TIMESTAMPTZ,
  cancel_reason     TEXT,
  solution          TEXT, -- Решение/что было сделано
  expected_return_date DATE, -- Ожидаемая дата возврата из ремонта
  attachments       TEXT[], -- Пути к файлам (фото проблемы и т.д.)
  comments          JSONB, -- [{ "author": "name", "text": "comment", "created_at": "timestamp" }]
  is_paid           BOOLEAN DEFAULT FALSE, -- Платный ремонт
  cost              NUMERIC(10, 2) DEFAULT 0, -- Стоимость ремонта
  cost_estimated    BOOLEAN DEFAULT FALSE, -- Стоимость предварительная (требуется диагностика)
  invoice_id        BIGINT, -- ID счета на оплату из финансов (если создан)
  invoice_url       TEXT, -- Ссылка на счет
  waiting_delivery_deadline  TEXT,   -- Примерный срок при ожидание поставки
  waiting_delivery_contacts  TEXT,   -- Контакты для уточнения поставки
  taken_for_repair_deadline  TEXT,   -- Срок при увезли на ремонт
  taken_for_repair_contacts  TEXT,   -- Контакты при увезли на ремонт
  agreed_contractor_price    NUMERIC(10, 2) -- Цена при договорились с подрядчиком
);

CREATE INDEX IF NOT EXISTS idx_repair_requests_equipment ON office_repair_requests(equipment_id);
CREATE INDEX IF NOT EXISTS idx_repair_requests_status ON office_repair_requests(status);
CREATE INDEX IF NOT EXISTS idx_repair_requests_created ON office_repair_requests(created_at DESC);

-- История перемещений и событий по оборудованию
CREATE TYPE office_equipment_history_type AS ENUM ('purchase', 'issue', 'transfer', 'repair', 'write_off');
CREATE TABLE IF NOT EXISTS office_equipment_history (
  id                BIGSERIAL PRIMARY KEY,
  equipment_id      BIGINT NOT NULL REFERENCES office_equipment(id) ON DELETE CASCADE,
  event_type        office_equipment_history_type NOT NULL,
  event_date        DATE NOT NULL,
  assigned_to       TEXT,   -- кому выдано / кому передано (для issue, transfer)
  assigned_from     TEXT,   -- от кого (для transfer)
  reason            TEXT,   -- причина (для repair, write_off)
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_equipment_history_equipment ON office_equipment_history(equipment_id);
CREATE INDEX IF NOT EXISTS idx_equipment_history_date ON office_equipment_history(event_date DESC);

-- ========= ОФИС: БАЗА ЗНАНИЙ =========

-- Категории базы знаний
CREATE TABLE IF NOT EXISTS knowledge_base_categories (
  id                BIGSERIAL PRIMARY KEY,
  name              TEXT NOT NULL,
  slug              TEXT NOT NULL UNIQUE,
  parent_id         BIGINT REFERENCES knowledge_base_categories(id) ON DELETE CASCADE,
  description       TEXT,
  icon              TEXT,
  sort_order        INTEGER DEFAULT 0,
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_kb_categories_parent ON knowledge_base_categories(parent_id);

-- Статьи базы знаний
CREATE TABLE IF NOT EXISTS knowledge_base_articles (
  id                BIGSERIAL PRIMARY KEY,
  title             TEXT NOT NULL,
  slug              TEXT NOT NULL UNIQUE,
  category_id       BIGINT REFERENCES knowledge_base_categories(id) ON DELETE SET NULL,
  content           TEXT NOT NULL, -- Markdown или HTML
  content_type      VARCHAR(10) NOT NULL DEFAULT 'markdown' CHECK (content_type IN ('markdown', 'html')),
  author            TEXT NOT NULL,
  version           INTEGER NOT NULL DEFAULT 1,
  parent_version_id BIGINT REFERENCES knowledge_base_articles(id) ON DELETE SET NULL, -- Для версионирования
  is_published      BOOLEAN DEFAULT TRUE,
  tags              TEXT[],
  attachments       TEXT[], -- Пути к прикрепленным файлам
  view_count        INTEGER DEFAULT 0,
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  published_at      TIMESTAMPTZ
);

CREATE INDEX IF NOT EXISTS idx_kb_articles_category ON knowledge_base_articles(category_id);
CREATE INDEX IF NOT EXISTS idx_kb_articles_slug ON knowledge_base_articles(slug);
CREATE INDEX IF NOT EXISTS idx_kb_articles_published ON knowledge_base_articles(is_published, published_at DESC);

-- ========= ОФИС: СОВЕЩАНИЯ И ПЕРЕГОВОРНЫЕ =========

-- Переговорные комнаты
CREATE TABLE IF NOT EXISTS meeting_rooms (
  id                BIGSERIAL PRIMARY KEY,
  name              TEXT NOT NULL,
  capacity          INTEGER NOT NULL,
  location          TEXT,
  equipment         TEXT[], -- ['projector', 'whiteboard', 'video_conference']
  description       TEXT,
  is_active         BOOLEAN DEFAULT TRUE,
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Совещания
CREATE TABLE IF NOT EXISTS meetings (
  id                BIGSERIAL PRIMARY KEY,
  title             TEXT NOT NULL,
  description       TEXT,
  organizer         TEXT NOT NULL,
  start_time        TIMESTAMPTZ NOT NULL,
  end_time          TIMESTAMPTZ NOT NULL,
  room_id           BIGINT REFERENCES meeting_rooms(id) ON DELETE SET NULL,
  participants      TEXT[] NOT NULL, -- Список участников
  agenda            TEXT, -- Повестка дня
  notes             TEXT, -- Заметки/протокол
  conclusions       TEXT, -- Заключения совещания
  status            VARCHAR(20) NOT NULL DEFAULT 'scheduled' CHECK (status IN ('scheduled', 'in_progress', 'completed', 'canceled')),
  reminder_sent     BOOLEAN DEFAULT FALSE,
  reminder_time     TIMESTAMPTZ, -- Когда отправлять напоминание
  attachments       TEXT[], -- Прикрепленные файлы
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  CHECK (end_time > start_time)
);

CREATE INDEX IF NOT EXISTS idx_meetings_room ON meetings(room_id);
CREATE INDEX IF NOT EXISTS idx_meetings_time ON meetings(start_time, end_time);
CREATE INDEX IF NOT EXISTS idx_meetings_status ON meetings(status);

-- Бронирования переговорных (отдельная таблица для истории)
CREATE TABLE IF NOT EXISTS meeting_bookings (
  id                BIGSERIAL PRIMARY KEY,
  room_id           BIGINT NOT NULL REFERENCES meeting_rooms(id) ON DELETE CASCADE,
  meeting_id        BIGINT REFERENCES meetings(id) ON DELETE CASCADE,
  booked_by         TEXT NOT NULL,
  start_time        TIMESTAMPTZ NOT NULL,
  end_time          TIMESTAMPTZ NOT NULL,
  purpose           TEXT,
  status            VARCHAR(20) NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'completed', 'canceled')),
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  CHECK (end_time > start_time)
  -- Примечание: проверка на пересечение времени выполняется на уровне приложения
  -- в API endpoint для предотвращения конфликтов бронирований
);

CREATE INDEX IF NOT EXISTS idx_meeting_bookings_room ON meeting_bookings(room_id);
CREATE INDEX IF NOT EXISTS idx_meeting_bookings_time ON meeting_bookings(start_time, end_time);
CREATE INDEX IF NOT EXISTS idx_meeting_bookings_status ON meeting_bookings(status);

-- ========= ОФИС: ЗАЯВКИ НА ТМЦ (КАНЦТОВАРЫ, ХОЗ. НУЖДЫ) =========

CREATE TABLE IF NOT EXISTS office_supply_requests (
  id                BIGSERIAL PRIMARY KEY,
  requester_name    TEXT NOT NULL, -- Сотрудник, создавший заявку
  category          VARCHAR(50) NOT NULL, -- 'stationery', 'household', 'food', 'other'
  item_name         TEXT NOT NULL,
  quantity          INTEGER DEFAULT 1,
  issued_quantity   INTEGER DEFAULT 0, -- Количество выданного сотруднику
  unit              VARCHAR(20) DEFAULT 'шт.',
  amount            NUMERIC(10, 2) DEFAULT 0,
  priority          VARCHAR(10) NOT NULL DEFAULT 'medium' CHECK (priority IN ('low', 'medium', 'high', 'urgent')),
  status            VARCHAR(20) NOT NULL DEFAULT 'new' CHECK (status IN ('new', 'approved', 'ordered', 'received', 'canceled', 'archived', 'collected')),
  approved_by       TEXT, -- Кто одобрил
  approved_at       TIMESTAMPTZ,
  ordered_at        TIMESTAMPTZ,
  received_at       TIMESTAMPTZ,
  notes             TEXT,
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_supply_requests_status ON office_supply_requests(status);
CREATE INDEX IF NOT EXISTS idx_supply_requests_requester ON office_supply_requests(requester_name);
CREATE INDEX IF NOT EXISTS idx_supply_requests_created ON office_supply_requests(created_at DESC);

-- ========= ОФИС: ЗАКАЗЫ =========
-- Заказы создаются из заявок на ТМЦ, могут включать несколько заявок
-- Заказ может ждать счет, иметь несколько предложений от поставщиков
CREATE TABLE IF NOT EXISTS office_orders (
  id                BIGSERIAL PRIMARY KEY,
  order_number      TEXT UNIQUE NOT NULL, -- Номер заказа (ORD-YYYY-MMDD-XXXX)
  title             TEXT NOT NULL, -- Название заказа
  description       TEXT, -- Описание заказа
  status            VARCHAR(20) NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'waiting_quote', 'quotes_received', 'approved', 'ordered', 'received', 'canceled')),
  total_amount      NUMERIC(10, 2) DEFAULT 0, -- Общая сумма заказа
  supplier_name     TEXT, -- Название поставщика
  supplier_contact  TEXT, -- Контакты поставщика
  invoice_id        BIGINT, -- ID счета на оплату из финансов (если создан)
  invoice_url       TEXT, -- Ссылка на счет
  expected_date     DATE, -- Ожидаемая дата получения
  received_date     DATE, -- Дата получения
  notes             TEXT,
  created_by        TEXT NOT NULL, -- Кто создал заказ
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Связь заказов с заявками (многие ко многим)
CREATE TABLE IF NOT EXISTS office_order_items (
  id                BIGSERIAL PRIMARY KEY,
  order_id          BIGINT NOT NULL REFERENCES office_orders(id) ON DELETE CASCADE,
  request_id        BIGINT NOT NULL REFERENCES office_supply_requests(id) ON DELETE CASCADE,
  quantity          INTEGER DEFAULT 1, -- Количество в заказе (может отличаться от заявки)
  unit_price        NUMERIC(10, 2) DEFAULT 0, -- Цена за единицу в заказе
  total_price       NUMERIC(10, 2) DEFAULT 0, -- Общая цена позиции
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  UNIQUE(order_id, request_id)
);

-- Предложения от поставщиков для заказа
CREATE TABLE IF NOT EXISTS office_order_quotes (
  id                BIGSERIAL PRIMARY KEY,
  order_id          BIGINT NOT NULL REFERENCES office_orders(id) ON DELETE CASCADE,
  supplier_name     TEXT NOT NULL,
  supplier_contact  TEXT,
  total_amount      NUMERIC(10, 2) NOT NULL,
  quote_file_url    TEXT, -- Файл с коммерческим предложением
  notes             TEXT,
  is_selected       BOOLEAN DEFAULT FALSE, -- Выбранное предложение
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_orders_status ON office_orders(status);
CREATE INDEX IF NOT EXISTS idx_orders_created ON office_orders(created_at DESC);
CREATE INDEX IF NOT EXISTS idx_order_items_order ON office_order_items(order_id);
CREATE INDEX IF NOT EXISTS idx_order_items_request ON office_order_items(request_id);
CREATE INDEX IF NOT EXISTS idx_order_quotes_order ON office_order_quotes(order_id);

-- ========= ОФИС: СКЛАД =========

CREATE TABLE IF NOT EXISTS office_inventory (
  id                BIGSERIAL PRIMARY KEY,
  name              TEXT NOT NULL,
  category          VARCHAR(50), -- 'stationery', 'household', 'food', 'other'
  quantity          NUMERIC(10, 2) NOT NULL DEFAULT 0,
  unit              VARCHAR(20) NOT NULL DEFAULT 'шт.',
  min_threshold     NUMERIC(10, 2) NOT NULL DEFAULT 0,
  last_restock      DATE,
  last_restock_by   TEXT, -- Кто пополнил
  location          TEXT, -- Место хранения
  notes             TEXT,
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_office_inventory_category ON office_inventory(category);
CREATE INDEX IF NOT EXISTS idx_office_inventory_name ON office_inventory(name);

-- ========= ОФИС: ДОКУМЕНТООБОРОТ =========

CREATE TABLE IF NOT EXISTS office_documents (
  id                BIGSERIAL PRIMARY KEY,
  reg_number        TEXT NOT NULL UNIQUE, -- Регистрационный номер
  title             TEXT NOT NULL,
  correspondent     TEXT NOT NULL, -- Корреспондент
  document_type     VARCHAR(20) NOT NULL CHECK (document_type IN ('incoming', 'outgoing')),
  status            VARCHAR(20) NOT NULL DEFAULT 'registered' CHECK (status IN ('registered', 'processed', 'sent', 'archived')),
  date              DATE NOT NULL,
  assigned_to       TEXT, -- Кому назначен
  tracking_number   TEXT, -- Трек-номер для отправленных
  file_url          TEXT, -- Путь к файлу
  notes             TEXT,
  created_by        TEXT NOT NULL, -- Кто создал/зарегистрировал
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_office_documents_reg_number ON office_documents(reg_number);
CREATE INDEX IF NOT EXISTS idx_office_documents_status ON office_documents(status);
CREATE INDEX IF NOT EXISTS idx_office_documents_type ON office_documents(document_type);
CREATE INDEX IF NOT EXISTS idx_office_documents_date ON office_documents(date DESC);
CREATE INDEX IF NOT EXISTS idx_office_documents_created_by ON office_documents(created_by);

-- ========= HR: СОТРУДНИКИ =========

CREATE TYPE employee_status AS ENUM ('active', 'vacation', 'inactive');
CREATE TYPE messenger_type AS ENUM ('Max', 'Telegram');

-- Основная таблица сотрудников
CREATE TABLE IF NOT EXISTS employees (
  id                VARCHAR(50) PRIMARY KEY,
  name              TEXT NOT NULL, -- ФИО
  position          TEXT NOT NULL, -- Должность
  phone             TEXT NOT NULL, -- Номер телефона
  status            employee_status NOT NULL DEFAULT 'active',
  salary            NUMERIC(10, 2) NOT NULL,
  assigned_district_id VARCHAR(50) REFERENCES districts(id) ON DELETE SET NULL,
  manager_id       VARCHAR(50) REFERENCES employees(id) ON DELETE SET NULL, -- Руководитель сотрудника
  birth_date        DATE,
  photo_url         TEXT,
  registration_date DATE,
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_employees_district ON employees(assigned_district_id);
CREATE INDEX IF NOT EXISTS idx_employees_status ON employees(status);
CREATE INDEX IF NOT EXISTS idx_employees_manager ON employees(manager_id);

-- ========= СТАТИСТИКА ПРОИЗВОДИТЕЛЬНОСТИ СОТРУДНИКОВ =========

CREATE TABLE IF NOT EXISTS employee_performance_stats (
  id                BIGSERIAL PRIMARY KEY,
  employee_name     TEXT NOT NULL,
  period_start      DATE NOT NULL,
  period_end        DATE NOT NULL,
  -- Статистика по заявкам
  total_assigned    INTEGER NOT NULL DEFAULT 0, -- Всего заявок назначено
  total_completed   INTEGER NOT NULL DEFAULT 0, -- Выполнено заявок
  total_overdue     INTEGER NOT NULL DEFAULT 0, -- Просрочено заявок
  total_in_progress INTEGER NOT NULL DEFAULT 0, -- В работе
  total_deferred    INTEGER NOT NULL DEFAULT 0, -- Отложено
  -- Расчётные показатели
  completion_rate   NUMERIC(5, 2) NOT NULL DEFAULT 0, -- Процент выполнения (с учётом общего контекста)
  overdue_rate      NUMERIC(5, 2) NOT NULL DEFAULT 0, -- Процент просрочек
  performance_score NUMERIC(5, 2) NOT NULL DEFAULT 0, -- Общий рейтинг производительности (0-100)
  -- Связи
  district_id       VARCHAR(50) REFERENCES districts(id) ON DELETE SET NULL,
  -- Метаданные
  calculated_at     TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  UNIQUE(employee_name, period_start, period_end)
);

CREATE INDEX IF NOT EXISTS idx_performance_stats_employee ON employee_performance_stats(employee_name);
CREATE INDEX IF NOT EXISTS idx_performance_stats_district ON employee_performance_stats(district_id);
CREATE INDEX IF NOT EXISTS idx_performance_stats_period ON employee_performance_stats(period_start, period_end);
CREATE INDEX IF NOT EXISTS idx_performance_stats_score ON employee_performance_stats(performance_score DESC);

-- ========= СТАТИСТИКА ПО УЧАСТКАМ =========

CREATE TABLE IF NOT EXISTS district_performance_stats (
  id                BIGSERIAL PRIMARY KEY,
  district_id       VARCHAR(50) NOT NULL REFERENCES districts(id) ON DELETE CASCADE,
  period_start      DATE NOT NULL,
  period_end        DATE NOT NULL,
  -- Статистика по заявкам
  total_applications INTEGER NOT NULL DEFAULT 0,
  total_completed    INTEGER NOT NULL DEFAULT 0,
  total_overdue      INTEGER NOT NULL DEFAULT 0,
  total_in_progress  INTEGER NOT NULL DEFAULT 0,
  -- Расчётные показатели
  completion_rate    NUMERIC(5, 2) NOT NULL DEFAULT 0,
  overdue_rate       NUMERIC(5, 2) NOT NULL DEFAULT 0,
  average_score      NUMERIC(5, 2) NOT NULL DEFAULT 0, -- Средний рейтинг сотрудников участка
  -- Метаданные
  calculated_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at         TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  UNIQUE(district_id, period_start, period_end)
);

CREATE INDEX IF NOT EXISTS idx_district_stats_district ON district_performance_stats(district_id);
CREATE INDEX IF NOT EXISTS idx_district_stats_period ON district_performance_stats(period_start, period_end);

-- Логины мессенджеров
CREATE TABLE IF NOT EXISTS employee_messenger_logins (
  id                BIGSERIAL PRIMARY KEY,
  employee_id       VARCHAR(50) NOT NULL REFERENCES employees(id) ON DELETE CASCADE,
  messenger         messenger_type NOT NULL,
  login             TEXT NOT NULL,
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  UNIQUE(employee_id, messenger)
);

CREATE INDEX IF NOT EXISTS idx_messenger_logins_employee ON employee_messenger_logins(employee_id);

-- HR данные: Паспортные данные
CREATE TABLE IF NOT EXISTS employee_passport_data (
  id                    BIGSERIAL PRIMARY KEY,
  employee_id           VARCHAR(50) NOT NULL REFERENCES employees(id) ON DELETE CASCADE,
  series                TEXT NOT NULL,
  number                TEXT NOT NULL,
  issued_by             TEXT NOT NULL,
  issued_date           DATE NOT NULL,
  registration_address  TEXT NOT NULL,
  created_at            TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at            TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  UNIQUE(employee_id)
);

CREATE INDEX IF NOT EXISTS idx_passport_data_employee ON employee_passport_data(employee_id);

-- HR данные: Трудовая книжка
CREATE TABLE IF NOT EXISTS employee_labor_books (
  id                BIGSERIAL PRIMARY KEY,
  employee_id       VARCHAR(50) NOT NULL REFERENCES employees(id) ON DELETE CASCADE,
  number            TEXT NOT NULL,
  series            TEXT,
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  UNIQUE(employee_id)
);

CREATE INDEX IF NOT EXISTS idx_labor_books_employee ON employee_labor_books(employee_id);

-- Записи в трудовой книжке
CREATE TABLE IF NOT EXISTS labor_book_entries (
  id                BIGSERIAL PRIMARY KEY,
  labor_book_id     BIGINT NOT NULL REFERENCES employee_labor_books(id) ON DELETE CASCADE,
  date              DATE NOT NULL,
  organization      TEXT NOT NULL,
  position          TEXT NOT NULL,
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_labor_book_entries_labor_book ON labor_book_entries(labor_book_id);

-- Заказ справок
CREATE TYPE certificate_status AS ENUM ('requested', 'issued', 'ready');

CREATE TABLE IF NOT EXISTS employee_certificates (
  id                BIGSERIAL PRIMARY KEY,
  employee_id       VARCHAR(50) NOT NULL REFERENCES employees(id) ON DELETE CASCADE,
  type              TEXT NOT NULL, -- Тип справки (2-НДФЛ, справка с места работы и т.д.)
  requested_date    DATE NOT NULL,
  issued_date       DATE,
  status            certificate_status NOT NULL DEFAULT 'requested',
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_certificates_employee ON employee_certificates(employee_id);
CREATE INDEX IF NOT EXISTS idx_certificates_status ON employee_certificates(status);

-- Прочие документы
CREATE TABLE IF NOT EXISTS employee_other_documents (
  id                BIGSERIAL PRIMARY KEY,
  employee_id       VARCHAR(50) NOT NULL REFERENCES employees(id) ON DELETE CASCADE,
  name              TEXT NOT NULL,
  type              TEXT NOT NULL,
  date              DATE NOT NULL,
  file_url          TEXT,
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_other_documents_employee ON employee_other_documents(employee_id);

-- Типовые документы HR (печать/шаблоны в разделе Кадры)
CREATE TABLE IF NOT EXISTS hr_template_documents (
  id                BIGSERIAL PRIMARY KEY,
  name              TEXT NOT NULL,
  file_path         TEXT NOT NULL,
  original_filename  TEXT,
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_hr_template_documents_created ON hr_template_documents(created_at DESC);

-- Бухгалтерская информация
CREATE TABLE IF NOT EXISTS employee_accounting_data (
  id                    BIGSERIAL PRIMARY KEY,
  employee_id           VARCHAR(50) NOT NULL REFERENCES employees(id) ON DELETE CASCADE,
  inn                   TEXT, -- ИНН
  snils                 TEXT, -- СНИЛС
  bank_name             TEXT, -- Название банка
  bank_account          TEXT, -- Расчетный счет
  correspondent_account TEXT, -- Корреспондентский счет
  bik                   TEXT, -- БИК
  tax_id                TEXT, -- КПП (если есть)
  created_at            TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at            TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  UNIQUE(employee_id)
);

CREATE INDEX IF NOT EXISTS idx_accounting_data_employee ON employee_accounting_data(employee_id);

-- Характеристики договора
CREATE TABLE IF NOT EXISTS employee_contracts (
  id                    BIGSERIAL PRIMARY KEY,
  employee_id           VARCHAR(50) NOT NULL REFERENCES employees(id) ON DELETE CASCADE,
  contract_type         TEXT NOT NULL, -- Тип договора (трудовой, ГПХ, срочный и т.д.)
  contract_number       TEXT, -- Номер договора
  start_date            DATE NOT NULL, -- Дата начала
  end_date              DATE, -- Дата окончания (NULL для бессрочного)
  probation_period_days INTEGER, -- Испытательный срок в днях
  work_schedule         TEXT, -- График работы (полный день, частичная занятость и т.д.)
  work_mode             TEXT, -- Режим работы (офис, удаленно, гибрид)
  contract_terms        TEXT, -- Дополнительные условия договора
  created_at            TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at            TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_contracts_employee ON employee_contracts(employee_id);
CREATE INDEX IF NOT EXISTS idx_contracts_dates ON employee_contracts(start_date, end_date);

-- ========= HR: ОТПУСКА =========

CREATE TABLE IF NOT EXISTS employee_vacations (
  id                BIGSERIAL PRIMARY KEY,
  employee_id       VARCHAR(50) NOT NULL REFERENCES employees(id) ON DELETE CASCADE,
  start_date        DATE NOT NULL,
  end_date          DATE NOT NULL,
  days_count        INTEGER NOT NULL, -- Количество дней отпуска
  vacation_type     TEXT NOT NULL DEFAULT 'annual', -- Тип отпуска (annual - ежегодный, unpaid - без сохранения зарплаты, study - учебный и т.д.)
  status            VARCHAR(20) NOT NULL DEFAULT 'planned' CHECK (status IN ('planned', 'approved', 'active', 'completed', 'canceled', 'rejected')),
  approved_by       TEXT, -- Кто утвердил
  approved_at       TIMESTAMPTZ, -- Дата утверждения
  notes             TEXT, -- Примечания
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  CHECK (end_date >= start_date)
);

CREATE INDEX IF NOT EXISTS idx_vacations_employee ON employee_vacations(employee_id);
CREATE INDEX IF NOT EXISTS idx_vacations_dates ON employee_vacations(start_date, end_date);
CREATE INDEX IF NOT EXISTS idx_vacations_status ON employee_vacations(status);

-- ========= HR: БОЛЬНИЧНЫЕ =========

CREATE TABLE IF NOT EXISTS employee_sick_leaves (
  id                BIGSERIAL PRIMARY KEY,
  employee_id       VARCHAR(50) NOT NULL REFERENCES employees(id) ON DELETE CASCADE,
  start_date        DATE NOT NULL,
  end_date          DATE, -- Может быть NULL, если больничный еще не закрыт
  days_count        INTEGER, -- Количество дней (рассчитывается автоматически)
  sick_leave_number TEXT, -- Номер больничного листа
  diagnosis         TEXT, -- Диагноз (если указан)
  medical_institution TEXT, -- Медицинское учреждение
  status            VARCHAR(20) NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'closed', 'canceled')),
  closed_at         TIMESTAMPTZ, -- Дата закрытия больничного
  expected_return_date DATE, -- Предварительная дата выхода
  notes             TEXT, -- Примечания
  file_url          TEXT, -- Ссылка на отсканированный больничный лист
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_sick_leaves_employee ON employee_sick_leaves(employee_id);
CREATE INDEX IF NOT EXISTS idx_sick_leaves_dates ON employee_sick_leaves(start_date, end_date);
CREATE INDEX IF NOT EXISTS idx_sick_leaves_status ON employee_sick_leaves(status);

-- ========= HR: УВОЛЬНЕНИЯ =========

CREATE TYPE termination_status AS ENUM ('initiated', 'in_progress', 'completed', 'canceled');

CREATE TABLE IF NOT EXISTS employee_terminations (
  id                    BIGSERIAL PRIMARY KEY,
  employee_id           VARCHAR(50) NOT NULL REFERENCES employees(id) ON DELETE CASCADE,
  termination_date      DATE NOT NULL, -- Дата увольнения
  reason                TEXT NOT NULL, -- Причина увольнения
  initiated_by          TEXT NOT NULL, -- Кто инициировал увольнение
  initiated_at          TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  status                termination_status NOT NULL DEFAULT 'initiated',
  -- Договор на увольнение
  termination_contract_number TEXT, -- Номер договора на увольнение
  termination_contract_date DATE, -- Дата договора
  termination_contract_file_url TEXT, -- Файл договора
  -- Расчеты
  final_settlement_amount NUMERIC(10, 2), -- Сумма окончательного расчета
  unused_vacation_days   INTEGER, -- Неиспользованные дни отпуска
  compensation_amount    NUMERIC(10, 2), -- Компенсация за неиспользованный отпуск
  severance_pay          NUMERIC(10, 2), -- Выходное пособие
  other_payments          NUMERIC(10, 2), -- Прочие выплаты
  deductions             NUMERIC(10, 2), -- Удержания
  settlement_document_number TEXT, -- Номер документа расчета
  settlement_document_date DATE, -- Дата документа расчета
  settlement_document_file_url TEXT, -- Файл документа расчета
  -- Дополнительная информация
  notes                  TEXT, -- Примечания
  completed_at           TIMESTAMPTZ, -- Дата завершения процедуры увольнения
  created_at             TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at             TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_terminations_employee ON employee_terminations(employee_id);
CREATE INDEX IF NOT EXISTS idx_terminations_date ON employee_terminations(termination_date);
CREATE INDEX IF NOT EXISTS idx_terminations_status ON employee_terminations(status);

-- ========= HR: ОТГУЛЫ И ПРОГУЛЫ =========

CREATE TABLE IF NOT EXISTS employee_absences (
  id                BIGSERIAL PRIMARY KEY,
  employee_id       VARCHAR(50) NOT NULL REFERENCES employees(id) ON DELETE CASCADE,
  absence_type      VARCHAR(20) NOT NULL CHECK (absence_type IN ('day_off', 'absence', 'late', 'early_leave')), -- Тип: отгул, прогул, опоздание, ранний уход
  start_date        DATE NOT NULL,
  end_date          DATE, -- Может быть NULL для однодневных отгулов
  start_time        TIME, -- Время начала (для опозданий и ранних уходов)
  end_time          TIME, -- Время окончания (для опозданий и ранних уходов)
  days_count        DECIMAL(5, 2) NOT NULL DEFAULT 1.0, -- Количество дней (может быть дробным для части дня)
  reason            TEXT, -- Причина отсутствия
  requires_approval BOOLEAN NOT NULL DEFAULT TRUE, -- Требуется ли согласование
  status            VARCHAR(20) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'approved', 'rejected', 'canceled')), -- Статус согласования
  approved_by       TEXT, -- Кто утвердил (руководитель)
  approved_at       TIMESTAMPTZ, -- Дата и время утверждения
  approved_signature TEXT, -- Подпись руководителя (текст или путь к файлу)
  rejected_by       TEXT, -- Кто отклонил
  rejected_at       TIMESTAMPTZ, -- Дата отклонения
  rejection_reason  TEXT, -- Причина отклонения
  notes             TEXT, -- Примечания
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  CHECK (end_date IS NULL OR end_date >= start_date)
);

CREATE INDEX IF NOT EXISTS idx_absences_employee ON employee_absences(employee_id);
CREATE INDEX IF NOT EXISTS idx_absences_dates ON employee_absences(start_date, end_date);
CREATE INDEX IF NOT EXISTS idx_absences_type ON employee_absences(absence_type);
CREATE INDEX IF NOT EXISTS idx_absences_status ON employee_absences(status);

-- Обновляем таблицу отпусков для поддержки согласования
ALTER TABLE employee_vacations 
  ADD COLUMN IF NOT EXISTS requires_approval BOOLEAN NOT NULL DEFAULT TRUE,
  ADD COLUMN IF NOT EXISTS approved_signature TEXT,
  ADD COLUMN IF NOT EXISTS rejected_by TEXT,
  ADD COLUMN IF NOT EXISTS rejected_at TIMESTAMPTZ,
  ADD COLUMN IF NOT EXISTS rejection_reason TEXT;

-- Обновляем таблицу больничных для поддержки согласования (если требуется)
ALTER TABLE employee_sick_leaves 
  ADD COLUMN IF NOT EXISTS requires_approval BOOLEAN NOT NULL DEFAULT FALSE,
  ADD COLUMN IF NOT EXISTS approved_by TEXT,
  ADD COLUMN IF NOT EXISTS approved_at TIMESTAMPTZ,
  ADD COLUMN IF NOT EXISTS approved_signature TEXT;

-- ========= ПРОФИЛИ ПОЛЬЗОВАТЕЛЕЙ ПОРТАЛА =========

-- Профили пользователей портала
-- Важно: профиль не может быть без сотрудника (employee_id NOT NULL)
-- Но сотрудник может быть без профиля (связь необязательная со стороны employees)
CREATE TABLE IF NOT EXISTS portal_users (
  id                BIGSERIAL PRIMARY KEY,
  employee_id       VARCHAR(50) NOT NULL REFERENCES employees(id) ON DELETE CASCADE,
  email             TEXT,
  login             TEXT UNIQUE,
  photo_url         TEXT, -- Путь к загруженному фото
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  UNIQUE(employee_id) -- Один профиль на одного сотрудника
);

CREATE INDEX IF NOT EXISTS idx_portal_users_employee ON portal_users(employee_id);
CREATE INDEX IF NOT EXISTS idx_portal_users_login ON portal_users(login);

-- Изменяем таблицу employees: photo_url теперь хранит путь к загруженному файлу
-- (или может быть NULL, если фото берется из профиля пользователя)

-- ========= HR: ВАКАНСИИ =========

-- Создание типа vacancy_status (с проверкой существования)
DO $$ 
BEGIN
    IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'vacancy_status') THEN
        CREATE TYPE vacancy_status AS ENUM ('urgent', 'active', 'paused', 'closed');
    END IF;
END$$;

-- Таблица вакансий
CREATE TABLE IF NOT EXISTS vacancies (
  id                VARCHAR(50) PRIMARY KEY,
  position          TEXT NOT NULL, -- Название должности
  department        TEXT NOT NULL, -- Отдел
  status            vacancy_status NOT NULL DEFAULT 'active',
  salary            TEXT, -- Вилка зарплаты (например, "55 000 - 65 000 ₽")
  description       TEXT NOT NULL, -- Описание вакансии
  requirements      TEXT, -- Требования к кандидату
  conditions        TEXT, -- Условия работы
  responsibilities  TEXT, -- Обязанности
  posted_date       DATE NOT NULL DEFAULT CURRENT_DATE, -- Дата публикации
  closing_date      DATE, -- Дата закрытия вакансии
  applicants_count  INTEGER DEFAULT 0, -- Количество откликов
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_vacancies_status ON vacancies(status);
CREATE INDEX IF NOT EXISTS idx_vacancies_department ON vacancies(department);
CREATE INDEX IF NOT EXISTS idx_vacancies_posted_date ON vacancies(posted_date DESC);

-- ========= HR: КАНДИДАТЫ =========

-- Создание типа candidate_stage (с проверкой существования)
DO $$ 
BEGIN
    IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'candidate_stage') THEN
        CREATE TYPE candidate_stage AS ENUM ('new', 'interview', 'probation', 'hired', 'rejected');
    ELSE
        -- Добавляем 'probation' если его еще нет
        IF NOT EXISTS (
            SELECT 1 FROM pg_enum 
            WHERE enumlabel = 'probation' 
            AND enumtypid = (SELECT oid FROM pg_type WHERE typname = 'candidate_stage')
        ) THEN
            ALTER TYPE candidate_stage ADD VALUE IF NOT EXISTS 'probation';
        END IF;
        -- Удаляем 'offer' если он есть (заменяем на 'probation')
        -- Примечание: удаление значений из ENUM в PostgreSQL невозможно напрямую,
        -- поэтому оставляем 'offer' для обратной совместимости, но не используем в новом коде
    END IF;
END$$;

-- Таблица кандидатов
CREATE TABLE IF NOT EXISTS candidates (
  id                VARCHAR(50) PRIMARY KEY,
  name              TEXT NOT NULL, -- ФИО кандидата
  position          TEXT NOT NULL, -- Позиция, на которую претендует
  vacancy_id        VARCHAR(50) REFERENCES vacancies(id) ON DELETE SET NULL, -- Связь с вакансией
  stage             candidate_stage NOT NULL DEFAULT 'new',
  phone             TEXT NOT NULL,
  email             TEXT,
  resume_url        TEXT, -- Ссылка на резюме
  cover_letter      TEXT, -- Сопроводительное письмо
  interview_date    TIMESTAMPTZ, -- Дата собеседования
  interview_notes   TEXT, -- Заметки с собеседования
  offer_salary      NUMERIC(10, 2), -- Предложенная зарплата
  offer_date        DATE, -- Дата предложения
  hired_date        DATE, -- Дата найма
  rejected_reason   TEXT, -- Причина отказа
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_candidates_vacancy ON candidates(vacancy_id);
CREATE INDEX IF NOT EXISTS idx_candidates_stage ON candidates(stage);
CREATE INDEX IF NOT EXISTS idx_candidates_position ON candidates(position);

-- ========= HR: СОБЫТИЯ КАНДИДАТОВ =========

-- Создание типа candidate_event_type
DO $$ 
BEGIN
    IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'candidate_event_type') THEN
        CREATE TYPE candidate_event_type AS ENUM (
            'call',              -- Созвон
            'interview_1',       -- Первое собеседование
            'interview_2',       -- Второе собеседование
            'interview_3',      -- Третье собеседование
            'test_task',         -- Тестовое задание
            'offer',             -- Оффер
            'offer_accepted',    -- Оффер принят
            'offer_rejected',    -- Оффер отклонен
            'probation_start',   -- Начало испытательного срока
            'hired',             -- Трудоустроен
            'rejected',          -- Отклонен
            'other'              -- Другое
        );
    END IF;
END$$;

-- Создание типа candidate_event_result
DO $$ 
BEGIN
    IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'candidate_event_result') THEN
        CREATE TYPE candidate_event_result AS ENUM ('success', 'failed', 'pending', 'cancelled');
    END IF;
END$$;

-- Таблица событий кандидата
CREATE TABLE IF NOT EXISTS candidate_events (
  id                VARCHAR(50) PRIMARY KEY,
  candidate_id      VARCHAR(50) NOT NULL REFERENCES candidates(id) ON DELETE CASCADE,
  event_type        candidate_event_type NOT NULL,
  event_date        TIMESTAMPTZ NOT NULL,
  notes             TEXT, -- Заметки о событии
  result            candidate_event_result DEFAULT 'pending', -- Результат события
  interviewer       TEXT, -- Кто проводил (для собеседований)
  location          TEXT, -- Место проведения (офис, онлайн и т.д.)
  duration_minutes  INTEGER, -- Длительность в минутах
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_candidate_events_candidate ON candidate_events(candidate_id);
CREATE INDEX IF NOT EXISTS idx_candidate_events_type ON candidate_events(event_type);
CREATE INDEX IF NOT EXISTS idx_candidate_events_date ON candidate_events(event_date DESC);


