-- ================================
-- TK-MP-Project 통합 데이터베이스 스키마
-- 다른 환경 배포용 완전한 초기화 스크립트
-- 생성일: 2025.09.09
-- ================================

-- ================================
-- 1. 기본 스키마 (01_schema.sql 기반)
-- ================================

-- 프로젝트 기본 정보
CREATE TABLE IF NOT EXISTS projects (
    id SERIAL PRIMARY KEY,
    
    -- 회사 공식 정보
    official_project_code VARCHAR(50) UNIQUE,           -- PP5-5701-DRYING (정식 코드)
    project_name VARCHAR(200) NOT NULL,
    client_name VARCHAR(100),
    
    -- 설계팀 사용 정보  
    design_project_code VARCHAR(50),                    -- 설계팀이 실제 사용한 코드
    design_project_name VARCHAR(200),                   -- 설계팀이 사용한 프로젝트명
    
    -- 매칭 정보
    is_code_matched BOOLEAN DEFAULT false,              -- 정식 코드 매칭 완료 여부
    matched_by VARCHAR(100),                            -- 매칭 작업자
    matched_at TIMESTAMP,                               -- 매칭 완료 시점
    
    -- 기본 정보
    status VARCHAR(20) DEFAULT 'active',                -- active/completed/on_hold
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    description TEXT,
    notes TEXT
);

-- 업로드된 자재 목록 파일들
CREATE TABLE IF NOT EXISTS files (
    id SERIAL PRIMARY KEY,
    project_id INTEGER REFERENCES projects(id) ON DELETE CASCADE,
    filename VARCHAR(255) NOT NULL,
    original_filename VARCHAR(255) NOT NULL,
    file_path VARCHAR(500) NOT NULL,
    revision VARCHAR(20) DEFAULT 'Rev.0',               -- Rev.0, Rev.1, Rev.2
    upload_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    uploaded_by VARCHAR(100),
    file_type VARCHAR(10),                              -- excel/csv/txt
    file_size INTEGER,
    is_active BOOLEAN DEFAULT true,
    
    -- 추가 필드 (19_add_user_tracking_fields.sql)
    updated_by VARCHAR(100),
    bom_name VARCHAR(200),                              -- BOM 이름 필드 추가
    
    -- 분류 관련 필드 (05_add_classification_columns.sql)
    classification_stats JSONB,
    classification_completed BOOLEAN DEFAULT FALSE,
    classification_timestamp TIMESTAMP,
    
    -- Job 연결 필드 (02_modify_files_table.sql)
    job_no VARCHAR(50),
    
    -- 파싱 통계 필드
    parsed_count INTEGER DEFAULT 0
);

-- 개별 자재 상세 정보
CREATE TABLE IF NOT EXISTS materials (
    id SERIAL PRIMARY KEY,
    file_id INTEGER REFERENCES files(id) ON DELETE CASCADE,
    line_number INTEGER,                                -- Excel 행 번호
    row_number INTEGER,                                 -- 실제 행 번호
    original_description TEXT NOT NULL,                 -- 원본 품명
    
    -- 분류 정보
    classified_category VARCHAR(50),                    -- 파이프/피팅/볼트/밸브/계기
    classified_subcategory VARCHAR(100),               -- 엘보우/플랜지/벤드 등
    
    -- 재질 및 스펙
    material_grade VARCHAR(50),                         -- A333-6, A105, SS316
    schedule VARCHAR(20),                               -- SCH40, SCH80, STD
    size_spec VARCHAR(50),                              -- 6인치, 150A, M16
    main_nom VARCHAR(50),                               -- 주 호칭 사이즈
    red_nom VARCHAR(50),                                -- 축소 호칭 사이즈
    
    -- 수량 정보
    quantity DECIMAL(10,3) NOT NULL,
    unit VARCHAR(10) NOT NULL,                          -- EA/mm/SET/kg
    
    -- 도면 정보
    drawing_name VARCHAR(100),                          -- P&ID-001-TANK
    area_code VARCHAR(20),                              -- #01, #02, #03
    line_no VARCHAR(50),                                -- LINE-001-A
    
    -- 분류 신뢰도 및 검증
    classification_confidence DECIMAL(3,2),             -- 0.00-1.00 분류 신뢰도
    classification_details JSONB,                       -- 분류 상세 정보 (JSON)
    is_verified BOOLEAN DEFAULT false,                  -- 사용자 검증 여부
    verified_by VARCHAR(100),
    verified_at TIMESTAMP,
    
    -- 구매 관련 필드
    purchase_confirmed BOOLEAN DEFAULT false,
    confirmed_quantity DECIMAL(10,3),
    purchase_status VARCHAR(20),
    purchase_confirmed_by VARCHAR(100),
    purchase_confirmed_at TIMESTAMP,
    
    -- 길이 정보 (05_add_length_to_materials.sql)
    length NUMERIC(10, 3),
    
    -- 사용자 추적 필드 (19_add_user_tracking_fields.sql)
    classified_by VARCHAR(100),
    classified_at TIMESTAMP,
    updated_by VARCHAR(100),
    
    -- 분류 상세 필드 (05_add_classification_columns.sql)
    subcategory VARCHAR(100),
    standard VARCHAR(200),
    grade VARCHAR(200),
    
    -- 해시 필드 (10_add_material_comparison_system.sql)
    material_hash VARCHAR(64),
    normalized_description TEXT,
    
    -- 기타
    drawing_reference VARCHAR(100),
    notes TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- ================================
-- 2. 자재 상세 정보 테이블들 (create_material_detail_tables.sql)
-- ================================

-- PIPE 상세 테이블
CREATE TABLE IF NOT EXISTS pipe_details (
    id SERIAL PRIMARY KEY,
    material_id INTEGER REFERENCES materials(id) ON DELETE CASCADE,
    file_id INTEGER REFERENCES files(id) ON DELETE CASCADE,
    
    -- 파이프 기본 정보
    outer_diameter VARCHAR(50),
    schedule VARCHAR(50),
    material_spec VARCHAR(100),
    manufacturing_method VARCHAR(50),
    end_preparation VARCHAR(50),
    
    -- 길이 정보
    length_mm DECIMAL(10,3),
    
    -- 신뢰도
    classification_confidence FLOAT,
    
    -- 추가 정보
    additional_info JSONB,
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- FITTING 상세 테이블
CREATE TABLE IF NOT EXISTS fitting_details (
    id SERIAL PRIMARY KEY,
    material_id INTEGER REFERENCES materials(id) ON DELETE CASCADE,
    file_id INTEGER REFERENCES files(id) ON DELETE CASCADE,
    
    -- 피팅 타입 정보
    fitting_type VARCHAR(50),
    fitting_subtype VARCHAR(50),
    
    -- 연결 방식
    connection_method VARCHAR(50),
    connection_code VARCHAR(50),
    
    -- 압력 등급
    pressure_rating VARCHAR(50),
    max_pressure VARCHAR(50),
    
    -- 제작 방법
    manufacturing_method VARCHAR(50),
    
    -- 재질 정보
    material_standard VARCHAR(100),
    material_grade VARCHAR(100),
    material_type VARCHAR(50),
    
    -- 사이즈 정보
    main_size VARCHAR(50),
    reduced_size VARCHAR(50),
    
    -- 길이 정보 (니플용)
    length_mm DECIMAL(10,3),
    schedule VARCHAR(50),
    
    -- 신뢰도
    classification_confidence FLOAT,
    
    -- 추가 정보
    additional_info JSONB,
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- VALVE 상세 테이블
CREATE TABLE IF NOT EXISTS valve_details (
    id SERIAL PRIMARY KEY,
    material_id INTEGER REFERENCES materials(id) ON DELETE CASCADE,
    file_id INTEGER REFERENCES files(id) ON DELETE CASCADE,
    
    -- 밸브 타입 정보
    valve_type VARCHAR(50),
    valve_subtype VARCHAR(50),
    actuator_type VARCHAR(50),
    
    -- 연결 방식
    connection_method VARCHAR(50),
    
    -- 압력 등급
    pressure_rating VARCHAR(50),
    pressure_class VARCHAR(50),
    
    -- 재질 정보
    body_material VARCHAR(100),
    trim_material VARCHAR(100),
    
    -- 사이즈 정보
    size_inches VARCHAR(50),
    
    -- 특수 사양
    fire_safe BOOLEAN,
    low_temp_service BOOLEAN,
    special_features JSONB,
    
    -- 신뢰도
    classification_confidence FLOAT,
    
    -- 추가 정보
    additional_info JSONB,
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- FLANGE 상세 테이블
CREATE TABLE IF NOT EXISTS flange_details (
    id SERIAL PRIMARY KEY,
    material_id INTEGER REFERENCES materials(id) ON DELETE CASCADE,
    file_id INTEGER REFERENCES files(id) ON DELETE CASCADE,
    
    -- 플랜지 타입
    flange_type VARCHAR(50),
    facing_type VARCHAR(50),
    
    -- 압력 등급
    pressure_rating VARCHAR(50),
    
    -- 재질 정보
    material_standard VARCHAR(100),
    material_grade VARCHAR(100),
    
    -- 사이즈 정보
    size_inches VARCHAR(50),
    bolt_hole_count INTEGER,
    bolt_hole_size VARCHAR(50),
    
    -- 신뢰도
    classification_confidence FLOAT,
    
    -- 추가 정보
    additional_info JSONB,
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- BOLT 상세 테이블
CREATE TABLE IF NOT EXISTS bolt_details (
    id SERIAL PRIMARY KEY,
    material_id INTEGER REFERENCES materials(id) ON DELETE CASCADE,
    file_id INTEGER REFERENCES files(id) ON DELETE CASCADE,
    
    -- 볼트 타입
    bolt_type VARCHAR(50),
    thread_type VARCHAR(50),
    
    -- 사양 정보
    diameter VARCHAR(50),
    length VARCHAR(50),
    
    -- 재질 정보
    material_standard VARCHAR(100),
    material_grade VARCHAR(100),
    coating_type VARCHAR(100),
    
    -- 압력 등급 (06_add_pressure_rating_to_bolt_details.sql)
    pressure_rating VARCHAR(50),
    
    -- 너트/와셔 정보
    includes_nut BOOLEAN,
    includes_washer BOOLEAN,
    nut_type VARCHAR(50),
    washer_type VARCHAR(50),
    
    -- 신뢰도
    classification_confidence FLOAT,
    
    -- 추가 정보
    additional_info JSONB,
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- GASKET 상세 테이블
CREATE TABLE IF NOT EXISTS gasket_details (
    id SERIAL PRIMARY KEY,
    material_id INTEGER REFERENCES materials(id) ON DELETE CASCADE,
    file_id INTEGER REFERENCES files(id) ON DELETE CASCADE,
    
    -- 가스켓 타입
    gasket_type VARCHAR(50),
    gasket_subtype VARCHAR(50),
    
    -- 재질 정보
    material_type VARCHAR(100),
    filler_material VARCHAR(100),
    
    -- 사이즈 및 등급
    size_inches VARCHAR(50),
    pressure_rating VARCHAR(50),
    thickness VARCHAR(50),
    
    -- 특수 사양
    temperature_range VARCHAR(100),
    fire_safe BOOLEAN,
    
    -- 신뢰도
    classification_confidence FLOAT,
    
    -- 추가 정보
    additional_info JSONB,
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- INSTRUMENT 상세 테이블
CREATE TABLE IF NOT EXISTS instrument_details (
    id SERIAL PRIMARY KEY,
    material_id INTEGER REFERENCES materials(id) ON DELETE CASCADE,
    file_id INTEGER REFERENCES files(id) ON DELETE CASCADE,
    
    -- 계장품 타입
    instrument_type VARCHAR(50),
    instrument_subtype VARCHAR(50),
    
    -- 측정 사양
    measurement_type VARCHAR(50),
    measurement_range VARCHAR(100),
    accuracy VARCHAR(50),
    
    -- 연결 정보
    connection_type VARCHAR(50),
    connection_size VARCHAR(50),
    
    -- 재질 정보
    body_material VARCHAR(100),
    wetted_parts_material VARCHAR(100),
    
    -- 전기 사양
    electrical_rating VARCHAR(100),
    output_signal VARCHAR(50),
    
    -- 신뢰도
    classification_confidence FLOAT,
    
    -- 추가 정보
    additional_info JSONB,
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- ================================
-- 3. 파이프 끝단 가공 테이블 (20_add_pipe_end_preparation_table.sql)
-- ================================

CREATE TABLE IF NOT EXISTS pipe_end_preparations (
    id SERIAL PRIMARY KEY,
    material_id INTEGER NOT NULL REFERENCES materials(id) ON DELETE CASCADE,
    file_id INTEGER NOT NULL REFERENCES files(id) ON DELETE CASCADE,
    
    -- 끝단 가공 정보
    end_preparation_type VARCHAR(50) DEFAULT 'PBE', -- PBE(양쪽무개선), BBE(양쪽개선), POE(한쪽개선), PE(무개선)
    end_preparation_code VARCHAR(20), -- 원본 코드 (BBE, POE, PBE 등)
    machining_required BOOLEAN DEFAULT FALSE, -- 가공 필요 여부
    cutting_note TEXT, -- 가공 메모
    
    -- 원본 정보 보존
    original_description TEXT NOT NULL, -- 끝단 가공 포함된 원본 설명
    clean_description TEXT NOT NULL,    -- 끝단 가공 제외한 구매용 설명
    
    -- 메타데이터
    confidence FLOAT DEFAULT 0.0, -- 분류 신뢰도
    matched_pattern VARCHAR(100), -- 매칭된 패턴
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- ================================
-- 4. 구매 관리 테이블들 (08_create_purchase_tables.sql)
-- ================================

-- 구매 품목 마스터 테이블
CREATE TABLE IF NOT EXISTS purchase_items (
    id SERIAL PRIMARY KEY,
    
    -- 품목 식별
    item_code VARCHAR(100) UNIQUE NOT NULL,     -- PI-PIPE-A106-4IN-001
    category VARCHAR(50) NOT NULL,              -- PIPE, VALVE, FITTING 등
    specification TEXT NOT NULL,                -- 상세 사양
    
    -- 기본 정보
    material_spec VARCHAR(200),                 -- ASTM A106 GR B
    size_spec VARCHAR(100),                     -- 4", 1-1/2" x 1"
    unit VARCHAR(10) NOT NULL,                  -- EA, mm, SET
    
    -- BOM 수량 정보
    bom_quantity DECIMAL(10,3) NOT NULL,        -- BOM상 필요 수량
    
    -- 구매 계산 정보
    safety_factor DECIMAL(3,2) DEFAULT 1.10,   -- 여유율 (1.1 = 10% 추가)
    minimum_order_qty DECIMAL(10,3) DEFAULT 0, -- 최소 주문 수량
    order_unit_qty DECIMAL(10,3) DEFAULT 1,    -- 주문 단위 (박스, 롤 등)
    calculated_qty DECIMAL(10,3),              -- 최종 계산된 구매 수량
    
    -- PIPE 전용 정보
    cutting_loss DECIMAL(10,3) DEFAULT 0,      -- 절단 손실 (mm)
    standard_length DECIMAL(10,3),             -- 표준 길이 (PIPE: 6000mm)
    pipes_count INTEGER,                        -- 필요한 파이프 본수
    waste_length DECIMAL(10,3),                -- 여유분 길이
    
    -- 상세 스펙 (JSON)
    detailed_spec JSONB,                        -- 압력등급, 연결방식 등 상세 정보
    
    -- 구매 정보
    preferred_supplier VARCHAR(200),           -- 선호 공급업체
    last_unit_price DECIMAL(10,2),            -- 최근 단가
    currency VARCHAR(10) DEFAULT 'KRW',        -- 통화
    lead_time_days INTEGER DEFAULT 30,         -- 리드타임
    
    -- 연결 정보
    job_no VARCHAR(50) NOT NULL,               -- Job 번호
    revision VARCHAR(20) DEFAULT 'Rev.0',      -- 리비전
    file_id INTEGER,                           -- 원본 파일 ID
    
    -- 관리 정보
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    created_by VARCHAR(100),
    updated_by VARCHAR(100),
    approved_by VARCHAR(100),
    approved_at TIMESTAMP,
    
    -- 외래키
    FOREIGN KEY (file_id) REFERENCES files(id) ON DELETE SET NULL
);

-- 개별 자재와 구매품목 연결 테이블
CREATE TABLE IF NOT EXISTS material_purchase_mapping (
    id SERIAL PRIMARY KEY,
    material_id INTEGER NOT NULL,              -- materials 테이블 ID
    purchase_item_id INTEGER NOT NULL,         -- purchase_items 테이블 ID
    quantity_ratio DECIMAL(5,2) DEFAULT 1.0,   -- 변환 비율
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    -- 외래키
    FOREIGN KEY (material_id) REFERENCES materials(id) ON DELETE CASCADE,
    FOREIGN KEY (purchase_item_id) REFERENCES purchase_items(id) ON DELETE CASCADE,
    
    -- 유니크 제약
    UNIQUE(material_id, purchase_item_id)
);

-- 구매 추적 테이블
CREATE TABLE IF NOT EXISTS material_purchase_tracking (
    id SERIAL PRIMARY KEY,
    material_hash VARCHAR(64) NOT NULL,
    
    -- 기본 정보
    original_description TEXT NOT NULL,
    size_spec VARCHAR(50),
    material_grade VARCHAR(50),
    
    -- 수량 정보
    bom_quantity DECIMAL(10,3) NOT NULL,
    confirmed_quantity DECIMAL(10,3),
    purchase_quantity DECIMAL(10,3),
    
    -- 상태 관리
    status VARCHAR(20) DEFAULT 'pending',
    confirmed_by VARCHAR(100),
    confirmed_at TIMESTAMP,
    ordered_by VARCHAR(100),
    ordered_at TIMESTAMP,
    approved_by VARCHAR(100),
    approved_at TIMESTAMP,
    
    -- 메타데이터
    job_no VARCHAR(50),
    revision VARCHAR(20),
    file_id INTEGER,
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    FOREIGN KEY (file_id) REFERENCES files(id) ON DELETE SET NULL
);

-- ================================
-- 6. Jobs 테이블 (01_create_jobs_table.sql)
-- ================================

CREATE TABLE IF NOT EXISTS jobs (
    -- 기본 정보
    job_no VARCHAR(50) PRIMARY KEY,
    job_name VARCHAR(200) NOT NULL,
    
    -- 계약 관계 (핵심)
    client_name VARCHAR(100) NOT NULL,
    
    -- 프로젝트 정보  
    end_user VARCHAR(100),
    epc_company VARCHAR(100),
    project_site VARCHAR(200),
    
    -- 상업 정보
    contract_date DATE,
    delivery_date DATE,
    delivery_terms VARCHAR(100),
    
    -- 상태 관리 (핵심)
    status VARCHAR(20) DEFAULT '진행중',
    delivery_completed_date DATE,
    project_closed_date DATE,
    
    -- 관리 정보
    description TEXT,
    created_by VARCHAR(50),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    is_active BOOLEAN DEFAULT true,
    
    -- 사용자 추적 필드 (19_add_user_tracking_fields.sql)
    updated_by VARCHAR(100),
    assigned_to VARCHAR(100),
    
    -- 프로젝트 타입 필드 (17_add_project_type_column.sql)
    project_type VARCHAR(50) DEFAULT '냉동기' NOT NULL
);

-- ================================
-- 7. 자재 규격/재질 기준표 테이블들 (05_create_material_standards_tables.sql)
-- ================================

-- 자재 규격 표준 테이블
CREATE TABLE IF NOT EXISTS material_standards (
    id SERIAL PRIMARY KEY,
    standard_code VARCHAR(20) UNIQUE NOT NULL,
    standard_name VARCHAR(100) NOT NULL,
    description TEXT,
    country VARCHAR(50),
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 제조방식별 카테고리 테이블
CREATE TABLE IF NOT EXISTS material_categories (
    id SERIAL PRIMARY KEY,
    standard_id INTEGER REFERENCES material_standards(id),
    category_code VARCHAR(50) NOT NULL,
    category_name VARCHAR(100) NOT NULL,
    description TEXT,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 구체적인 규격 테이블
CREATE TABLE IF NOT EXISTS material_specifications (
    id SERIAL PRIMARY KEY,
    category_id INTEGER REFERENCES material_categories(id),
    spec_code VARCHAR(20) NOT NULL,
    spec_name VARCHAR(100) NOT NULL,
    description TEXT,
    material_type VARCHAR(50),
    manufacturing VARCHAR(50),
    pressure_rating VARCHAR(100),
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 등급별 상세 정보 테이블
CREATE TABLE IF NOT EXISTS material_grades (
    id SERIAL PRIMARY KEY,
    specification_id INTEGER REFERENCES material_specifications(id),
    grade_code VARCHAR(20) NOT NULL,
    grade_name VARCHAR(100),
    composition VARCHAR(200),
    applications VARCHAR(200),
    temp_max VARCHAR(50),
    temp_range VARCHAR(100),
    yield_strength VARCHAR(50),
    tensile_strength VARCHAR(50),
    corrosion_resistance VARCHAR(50),
    stabilizer VARCHAR(50),
    base_grade VARCHAR(20),
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 정규식 패턴 테이블
CREATE TABLE IF NOT EXISTS material_patterns (
    id SERIAL PRIMARY KEY,
    specification_id INTEGER REFERENCES material_specifications(id),
    pattern TEXT NOT NULL,
    description VARCHAR(200),
    priority INTEGER DEFAULT 1,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 특수 재질 테이블
CREATE TABLE IF NOT EXISTS special_materials (
    id SERIAL PRIMARY KEY,
    material_type VARCHAR(50) NOT NULL,
    material_name VARCHAR(100) NOT NULL,
    description TEXT,
    composition VARCHAR(200),
    applications TEXT,
    temp_max VARCHAR(50),
    manufacturing VARCHAR(50),
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 특수 재질 등급 테이블
CREATE TABLE IF NOT EXISTS special_material_grades (
    id SERIAL PRIMARY KEY,
    material_id INTEGER REFERENCES special_materials(id),
    grade_code VARCHAR(20) NOT NULL,
    composition VARCHAR(200),
    applications VARCHAR(200),
    temp_max VARCHAR(50),
    strength VARCHAR(50),
    purity VARCHAR(100),
    corrosion VARCHAR(50),
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 특수 재질 정규식 패턴 테이블
CREATE TABLE IF NOT EXISTS special_material_patterns (
    id SERIAL PRIMARY KEY,
    material_id INTEGER REFERENCES special_materials(id),
    pattern TEXT NOT NULL,
    description VARCHAR(200),
    priority INTEGER DEFAULT 1,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- ================================
-- 8. 자재 비교 및 발주 추적 시스템 (10_add_material_comparison_system.sql)
-- ================================

-- 자재 비교 결과 저장 테이블
CREATE TABLE IF NOT EXISTS material_revisions_comparison (
    id SERIAL PRIMARY KEY,
    
    -- 비교 기본 정보
    job_no VARCHAR(50) NOT NULL,
    current_revision VARCHAR(20) NOT NULL,
    previous_revision VARCHAR(20) NOT NULL,
    current_file_id INTEGER NOT NULL,
    previous_file_id INTEGER NOT NULL,
    
    -- 비교 결과 요약
    total_current_items INTEGER DEFAULT 0,
    total_previous_items INTEGER DEFAULT 0,
    new_items_count INTEGER DEFAULT 0,
    modified_items_count INTEGER DEFAULT 0,
    removed_items_count INTEGER DEFAULT 0,
    unchanged_items_count INTEGER DEFAULT 0,
    
    -- 상세 결과 (JSON)
    comparison_details JSONB,
    
    -- 관리 정보
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    created_by VARCHAR(100),
    
    -- 외래키
    FOREIGN KEY (current_file_id) REFERENCES files(id),
    FOREIGN KEY (previous_file_id) REFERENCES files(id),
    
    -- 유니크 제약 (같은 비교는 한 번만)
    UNIQUE(job_no, current_revision, previous_revision)
);

-- 개별 자재 비교 상세 테이블
CREATE TABLE IF NOT EXISTS material_comparison_details (
    id SERIAL PRIMARY KEY,
    
    comparison_id INTEGER NOT NULL,
    material_hash VARCHAR(32) NOT NULL,
    
    -- 비교 타입
    change_type VARCHAR(20) NOT NULL, -- 'NEW', 'MODIFIED', 'REMOVED', 'UNCHANGED'
    
    -- 자재 정보
    description TEXT NOT NULL,
    size_spec VARCHAR(100),
    material_grade VARCHAR(100),
    
    -- 수량 비교
    previous_quantity DECIMAL(10,3) DEFAULT 0,
    current_quantity DECIMAL(10,3) DEFAULT 0,
    quantity_diff DECIMAL(10,3) DEFAULT 0,
    
    -- 추가 구매 필요량 (핵심!)
    additional_purchase_needed DECIMAL(10,3) DEFAULT 0,
    
    -- 분류 정보
    classified_category VARCHAR(50),
    classification_confidence DECIMAL(3,2),
    
    -- 관리 정보
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    -- 외래키
    FOREIGN KEY (comparison_id) REFERENCES material_revisions_comparison(id) ON DELETE CASCADE
);

-- ================================
-- 9. Tubing 시스템 테이블들 (15_create_tubing_system.sql)
-- ================================

-- Tubing 카테고리 테이블
CREATE TABLE IF NOT EXISTS tubing_categories (
    id SERIAL PRIMARY KEY,
    category_code VARCHAR(20) UNIQUE NOT NULL,
    category_name VARCHAR(100) NOT NULL,
    description TEXT,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Tubing 규격 마스터 테이블
CREATE TABLE IF NOT EXISTS tubing_specifications (
    id SERIAL PRIMARY KEY,
    category_id INTEGER REFERENCES tubing_categories(id),
    spec_code VARCHAR(50) UNIQUE NOT NULL,
    spec_name VARCHAR(200) NOT NULL,
    
    -- 물리적 규격
    outer_diameter_mm DECIMAL(8,3),           -- 외경 (mm)
    wall_thickness_mm DECIMAL(6,3),          -- 두께 (mm)
    inner_diameter_mm DECIMAL(8,3),          -- 내경 (mm, 계산 또는 실측)
    
    -- 재질 정보
    material_grade VARCHAR(100),             -- SS316, SS316L, Inconel625 등
    material_standard VARCHAR(100),          -- ASTM A269, JIS G3463 등
    
    -- 압력/온도 등급
    max_pressure_bar DECIMAL(8,2),          -- 최대 압력 (bar)
    max_temperature_c DECIMAL(6,2),         -- 최대 온도 (°C)
    min_temperature_c DECIMAL(6,2),         -- 최소 온도 (°C)
    
    -- 표준 규격
    standard_length_m DECIMAL(8,3),         -- 표준 길이 (m)
    bend_radius_min_mm DECIMAL(8,2),        -- 최소 벤딩 반경 (mm)
    
    -- 기타 정보
    surface_finish VARCHAR(100),            -- 표면 마감 (BA, #4, 2B 등)
    hardness VARCHAR(50),                   -- 경도
    notes TEXT,
    
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 제조사 정보 테이블
CREATE TABLE IF NOT EXISTS tubing_manufacturers (
    id SERIAL PRIMARY KEY,
    manufacturer_code VARCHAR(20) UNIQUE NOT NULL,
    manufacturer_name VARCHAR(200) NOT NULL,
    country VARCHAR(100),
    website VARCHAR(500),
    contact_info JSONB,                     -- 연락처 정보 (JSON)
    quality_certs JSONB,                    -- 품질 인증서 정보 (ISO, API 등)
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 제조사별 제품 테이블
CREATE TABLE IF NOT EXISTS tubing_products (
    id SERIAL PRIMARY KEY,
    specification_id INTEGER REFERENCES tubing_specifications(id),
    manufacturer_id INTEGER REFERENCES tubing_manufacturers(id),
    
    -- 제조사 품목번호 정보
    manufacturer_part_number VARCHAR(200) NOT NULL,  -- 제조사 품목번호
    manufacturer_product_name VARCHAR(300),          -- 제조사 제품명
    
    -- 가격/공급 정보
    list_price DECIMAL(12,2),                       -- 정가
    currency VARCHAR(10) DEFAULT 'KRW',             -- 통화
    lead_time_days INTEGER,                         -- 리드타임 (일)
    minimum_order_qty DECIMAL(10,3),                -- 최소 주문 수량
    standard_packaging_qty DECIMAL(10,3),           -- 표준 포장 수량
    
    -- 가용성 정보
    availability_status VARCHAR(50),                -- 재고 상태
    last_price_update DATE,                         -- 마지막 가격 업데이트
    
    -- 추가 정보
    datasheet_url VARCHAR(500),                     -- 데이터시트 URL
    catalog_page VARCHAR(100),                      -- 카탈로그 페이지
    notes TEXT,
    
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    -- 유니크 제약 (같은 규격의 같은 제조사 제품은 하나만)
    UNIQUE(specification_id, manufacturer_id, manufacturer_part_number)
);

-- BOM에서 사용되는 Tubing 매핑 테이블
CREATE TABLE IF NOT EXISTS material_tubing_mapping (
    id SERIAL PRIMARY KEY,
    material_id INTEGER REFERENCES materials(id) ON DELETE CASCADE,
    tubing_product_id INTEGER REFERENCES tubing_products(id),
    
    -- 매핑 정보
    confidence_score DECIMAL(3,2),                  -- 매핑 신뢰도 (0.00-1.00)
    mapping_method VARCHAR(50),                     -- 매핑 방법 (auto/manual)
    mapped_by VARCHAR(100),                         -- 매핑한 사용자
    mapped_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    -- 수량 정보
    required_length_m DECIMAL(10,3),                -- 필요 길이 (m)
    calculated_quantity DECIMAL(10,3),              -- 계산된 주문 수량
    
    -- 검증 정보
    is_verified BOOLEAN DEFAULT FALSE,
    verified_by VARCHAR(100),
    verified_at TIMESTAMP,
    
    notes TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- ================================
-- 10. 사용자 요구사항 테이블들 (05_create_pipe_details_and_requirements_postgres.sql)
-- ================================

-- 요구사항 타입 마스터 테이블
CREATE TABLE IF NOT EXISTS requirement_types (
    id SERIAL PRIMARY KEY,
    type_code VARCHAR(50) UNIQUE NOT NULL,    -- 'IMPACT_TEST', 'HEAT_TREATMENT' 등
    type_name VARCHAR(100) NOT NULL,          -- '임팩테스트', '열처리' 등
    category VARCHAR(50) NOT NULL,            -- 'TEST', 'TREATMENT', 'CERTIFICATION', 'CUSTOM' 등
    description TEXT,                         -- 타입 설명
    is_active BOOLEAN DEFAULT TRUE,
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 사용자 추가 요구사항 테이블
CREATE TABLE IF NOT EXISTS user_requirements (
    id SERIAL PRIMARY KEY,
    file_id INTEGER NOT NULL,
    material_id INTEGER,                      -- 자재 ID (개별 자재별 요구사항 연결)
    
    -- 요구사항 타입
    requirement_type VARCHAR(50) NOT NULL,     -- 'IMPACT_TEST', 'HEAT_TREATMENT', 'CUSTOM_SPEC', 'CERTIFICATION' 등
    
    -- 요구사항 내용
    requirement_title VARCHAR(200) NOT NULL,   -- '임팩테스트', '열처리', '인증서' 등
    requirement_description TEXT,              -- 상세 설명
    requirement_spec TEXT,                    -- 구체적 스펙 (예: "Charpy V-notch -20°C")
    
    -- 상태 관리
    status VARCHAR(20) DEFAULT 'PENDING',     -- 'PENDING', 'IN_PROGRESS', 'COMPLETED', 'CANCELLED'
    priority VARCHAR(20) DEFAULT 'NORMAL',    -- 'LOW', 'NORMAL', 'HIGH', 'URGENT'
    
    -- 담당자 정보
    assigned_to VARCHAR(100),                 -- 담당자명
    due_date DATE,                           -- 완료 예정일
    
    -- 메타데이터
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    FOREIGN KEY (file_id) REFERENCES files(id) ON DELETE CASCADE,
    FOREIGN KEY (material_id) REFERENCES materials(id) ON DELETE CASCADE
);

-- ================================
-- 11. 사용자 활동 로그 테이블 (19_add_user_tracking_fields.sql)
-- ================================

CREATE TABLE IF NOT EXISTS user_activity_logs (
    id SERIAL PRIMARY KEY,
    user_id INTEGER,                         -- users 테이블 참조 (외래키 제약 없음 - 유연성)
    username VARCHAR(100) NOT NULL,          -- 사용자명 (필수)
    
    -- 활동 정보
    activity_type VARCHAR(50) NOT NULL,      -- 'FILE_UPLOAD', 'PROJECT_CREATE', 'PURCHASE_CONFIRM' 등
    activity_description TEXT,               -- 상세 활동 내용
    
    -- 대상 정보
    target_id INTEGER,                       -- 대상 ID (파일, 프로젝트 등)
    target_type VARCHAR(50),                 -- 'FILE', 'PROJECT', 'MATERIAL', 'PURCHASE' 등
    
    -- 세션 정보
    ip_address VARCHAR(45),                  -- IP 주소
    user_agent TEXT,                         -- 브라우저 정보
    
    -- 추가 메타데이터 (JSON)
    metadata JSONB,                          -- 추가 정보 (파일 크기, 처리 시간 등)
    
    -- 시간 정보
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- ================================
-- 7. 인덱스 생성 (성능 최적화)
-- ================================

-- 프로젝트 관련 인덱스
CREATE INDEX IF NOT EXISTS idx_projects_official_code ON projects(official_project_code);
CREATE INDEX IF NOT EXISTS idx_projects_design_code ON projects(design_project_code);

-- 파일 관련 인덱스
CREATE INDEX IF NOT EXISTS idx_files_project ON files(project_id);
CREATE INDEX IF NOT EXISTS idx_files_active ON files(is_active);
CREATE INDEX IF NOT EXISTS idx_files_uploaded_by ON files(uploaded_by);
CREATE INDEX IF NOT EXISTS idx_files_updated_by ON files(updated_by);

-- 자재 관련 인덱스
CREATE INDEX IF NOT EXISTS idx_materials_file ON materials(file_id);
CREATE INDEX IF NOT EXISTS idx_materials_category ON materials(classified_category, classified_subcategory);
CREATE INDEX IF NOT EXISTS idx_materials_material_size ON materials(material_grade, size_spec);
CREATE INDEX IF NOT EXISTS idx_materials_classified_by ON materials(classified_by);
CREATE INDEX IF NOT EXISTS idx_materials_hash ON materials(material_hash);

-- 자재 상세 테이블 인덱스
CREATE INDEX IF NOT EXISTS idx_pipe_details_material_id ON pipe_details(material_id);
CREATE INDEX IF NOT EXISTS idx_pipe_details_file_id ON pipe_details(file_id);

CREATE INDEX IF NOT EXISTS idx_fitting_details_material_id ON fitting_details(material_id);
CREATE INDEX IF NOT EXISTS idx_fitting_details_file_id ON fitting_details(file_id);
CREATE INDEX IF NOT EXISTS idx_fitting_details_type ON fitting_details(fitting_type);

CREATE INDEX IF NOT EXISTS idx_valve_details_material_id ON valve_details(material_id);
CREATE INDEX IF NOT EXISTS idx_valve_details_file_id ON valve_details(file_id);
CREATE INDEX IF NOT EXISTS idx_valve_details_type ON valve_details(valve_type);

CREATE INDEX IF NOT EXISTS idx_flange_details_material_id ON flange_details(material_id);
CREATE INDEX IF NOT EXISTS idx_flange_details_file_id ON flange_details(file_id);

CREATE INDEX IF NOT EXISTS idx_bolt_details_material_id ON bolt_details(material_id);
CREATE INDEX IF NOT EXISTS idx_bolt_details_file_id ON bolt_details(file_id);

CREATE INDEX IF NOT EXISTS idx_gasket_details_material_id ON gasket_details(material_id);
CREATE INDEX IF NOT EXISTS idx_gasket_details_file_id ON gasket_details(file_id);

CREATE INDEX IF NOT EXISTS idx_instrument_details_material_id ON instrument_details(material_id);
CREATE INDEX IF NOT EXISTS idx_instrument_details_file_id ON instrument_details(file_id);

-- 파이프 끝단 가공 테이블 인덱스
CREATE INDEX IF NOT EXISTS idx_pipe_end_preparations_material_id ON pipe_end_preparations(material_id);
CREATE INDEX IF NOT EXISTS idx_pipe_end_preparations_file_id ON pipe_end_preparations(file_id);
CREATE INDEX IF NOT EXISTS idx_pipe_end_preparations_type ON pipe_end_preparations(end_preparation_type);

-- 구매 관련 인덱스
CREATE INDEX IF NOT EXISTS idx_purchase_items_job_revision ON purchase_items(job_no, revision);
CREATE INDEX IF NOT EXISTS idx_purchase_items_category ON purchase_items(category);
CREATE INDEX IF NOT EXISTS idx_purchase_items_item_code ON purchase_items(item_code);
CREATE INDEX IF NOT EXISTS idx_purchase_items_active ON purchase_items(is_active);

CREATE INDEX IF NOT EXISTS idx_material_purchase_mapping_material ON material_purchase_mapping(material_id);
CREATE INDEX IF NOT EXISTS idx_material_purchase_mapping_purchase ON material_purchase_mapping(purchase_item_id);

CREATE INDEX IF NOT EXISTS idx_material_purchase_tracking_hash ON material_purchase_tracking(material_hash);
CREATE INDEX IF NOT EXISTS idx_material_purchase_tracking_job_revision ON material_purchase_tracking(job_no, revision);

-- Jobs 테이블 인덱스
CREATE INDEX IF NOT EXISTS idx_jobs_status ON jobs(status);
CREATE INDEX IF NOT EXISTS idx_jobs_client ON jobs(client_name);
CREATE INDEX IF NOT EXISTS idx_jobs_created_at ON jobs(created_at);
CREATE INDEX IF NOT EXISTS idx_jobs_created_by ON jobs(created_by);
CREATE INDEX IF NOT EXISTS idx_jobs_assigned_to ON jobs(assigned_to);

-- 자재 규격/재질 기준표 인덱스
CREATE INDEX IF NOT EXISTS idx_material_standards_code ON material_standards(standard_code);
CREATE INDEX IF NOT EXISTS idx_material_categories_standard ON material_categories(standard_id);
CREATE INDEX IF NOT EXISTS idx_material_specifications_category ON material_specifications(category_id);
CREATE INDEX IF NOT EXISTS idx_material_grades_specification ON material_grades(specification_id);
CREATE INDEX IF NOT EXISTS idx_material_patterns_specification ON material_patterns(specification_id);
CREATE INDEX IF NOT EXISTS idx_special_materials_type ON special_materials(material_type);
CREATE INDEX IF NOT EXISTS idx_special_material_grades_material ON special_material_grades(material_id);
CREATE INDEX IF NOT EXISTS idx_special_material_patterns_material ON special_material_patterns(material_id);

-- 활성 상태 인덱스
CREATE INDEX IF NOT EXISTS idx_material_standards_active ON material_standards(is_active);
CREATE INDEX IF NOT EXISTS idx_material_categories_active ON material_categories(is_active);
CREATE INDEX IF NOT EXISTS idx_material_specifications_active ON material_specifications(is_active);
CREATE INDEX IF NOT EXISTS idx_material_grades_active ON material_grades(is_active);
CREATE INDEX IF NOT EXISTS idx_material_patterns_active ON material_patterns(is_active);
CREATE INDEX IF NOT EXISTS idx_special_materials_active ON special_materials(is_active);
CREATE INDEX IF NOT EXISTS idx_special_material_grades_active ON special_material_grades(is_active);
CREATE INDEX IF NOT EXISTS idx_special_material_patterns_active ON special_material_patterns(is_active);

-- 자재 비교 시스템 인덱스
CREATE INDEX IF NOT EXISTS idx_material_revisions_job ON material_revisions_comparison(job_no);
CREATE INDEX IF NOT EXISTS idx_material_revisions_current ON material_revisions_comparison(current_revision);
CREATE INDEX IF NOT EXISTS idx_material_comparison_hash ON material_comparison_details(material_hash);
CREATE INDEX IF NOT EXISTS idx_material_comparison_type ON material_comparison_details(change_type);

-- Tubing 시스템 인덱스
CREATE INDEX IF NOT EXISTS idx_tubing_specs_category ON tubing_specifications(category_id);
CREATE INDEX IF NOT EXISTS idx_tubing_specs_material ON tubing_specifications(material_grade);
CREATE INDEX IF NOT EXISTS idx_tubing_specs_diameter ON tubing_specifications(outer_diameter_mm, wall_thickness_mm);
CREATE INDEX IF NOT EXISTS idx_tubing_products_spec ON tubing_products(specification_id);
CREATE INDEX IF NOT EXISTS idx_tubing_products_manufacturer ON tubing_products(manufacturer_id);
CREATE INDEX IF NOT EXISTS idx_tubing_products_part_number ON tubing_products(manufacturer_part_number);
CREATE INDEX IF NOT EXISTS idx_material_tubing_mapping_material ON material_tubing_mapping(material_id);
CREATE INDEX IF NOT EXISTS idx_material_tubing_mapping_product ON material_tubing_mapping(tubing_product_id);

-- 사용자 활동 로그 인덱스
CREATE INDEX IF NOT EXISTS idx_user_activity_logs_username ON user_activity_logs(username);
CREATE INDEX IF NOT EXISTS idx_user_activity_logs_activity_type ON user_activity_logs(activity_type);
CREATE INDEX IF NOT EXISTS idx_user_activity_logs_created_at ON user_activity_logs(created_at);
CREATE INDEX IF NOT EXISTS idx_user_activity_logs_target ON user_activity_logs(target_type, target_id);

-- ================================
-- SPECIAL 카테고리 지원 테이블
-- ================================

-- SPECIAL 키워드 패턴 테이블
CREATE TABLE IF NOT EXISTS special_classification_patterns (
    id SERIAL PRIMARY KEY,
    pattern_type VARCHAR(20) NOT NULL, -- 'KEYWORD', 'REGEX', 'EXACT'
    pattern_value VARCHAR(200) NOT NULL,
    description TEXT,
    priority INTEGER DEFAULT 1, -- 우선순위 (낮을수록 높은 우선순위)
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- SPECIAL 자재 상세 정보 테이블 (도면 업로드 관련)
CREATE TABLE IF NOT EXISTS special_material_details (
    id SERIAL PRIMARY KEY,
    material_id INTEGER REFERENCES materials(id) ON DELETE CASCADE,
    file_id INTEGER REFERENCES files(id) ON DELETE CASCADE,
    
    -- 도면 정보
    drawing_number VARCHAR(100), -- 도면 번호
    drawing_revision VARCHAR(20), -- 도면 리비전
    drawing_uploaded BOOLEAN DEFAULT FALSE, -- 도면 업로드 여부
    drawing_file_path TEXT, -- 도면 파일 경로
    
    -- 특수 요구사항
    special_requirements TEXT, -- 특수 제작 요구사항
    manufacturing_notes TEXT, -- 제작 참고사항
    approval_required BOOLEAN DEFAULT TRUE, -- 승인 필요 여부
    approved_by VARCHAR(100), -- 승인자
    approved_at TIMESTAMP, -- 승인 일시
    
    -- 분류 정보
    classification_confidence FLOAT DEFAULT 1.0,
    classification_reason TEXT, -- 분류 근거
    
    -- 관리 정보
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- ================================
-- 추가 성능 최적화 인덱스 (16_performance_indexes.sql)
-- ================================

-- 복합 인덱스 (자주 함께 사용되는 컬럼들)
CREATE INDEX IF NOT EXISTS idx_files_job_revision ON files(job_no, revision) WHERE is_active = true;
CREATE INDEX IF NOT EXISTS idx_files_job_date ON files(job_no, upload_date DESC) WHERE is_active = true;
CREATE INDEX IF NOT EXISTS idx_materials_file_category ON materials(file_id, classified_category);
CREATE INDEX IF NOT EXISTS idx_materials_category_grade ON materials(classified_category, material_grade);

-- 검색 성능 향상 인덱스
CREATE INDEX IF NOT EXISTS idx_materials_description_gin ON materials USING gin(to_tsvector('english', original_description));

-- 정렬 성능 향상 인덱스
CREATE INDEX IF NOT EXISTS idx_jobs_status_created ON jobs(status, created_at DESC) WHERE is_active = true;
CREATE INDEX IF NOT EXISTS idx_materials_quantity_desc ON materials(quantity DESC);

-- 조건부 인덱스 (특정 조건에서만 사용)
CREATE INDEX IF NOT EXISTS idx_materials_unverified ON materials(classified_category, classification_confidence) WHERE is_verified = false;
CREATE INDEX IF NOT EXISTS idx_materials_low_confidence ON materials(file_id, classified_category) WHERE classification_confidence < 0.8;

-- SPECIAL 카테고리 전용 인덱스
CREATE INDEX IF NOT EXISTS idx_materials_special_category ON materials(classified_category) WHERE classified_category = 'SPECIAL';
CREATE INDEX IF NOT EXISTS idx_special_patterns_type ON special_classification_patterns(pattern_type);
CREATE INDEX IF NOT EXISTS idx_special_patterns_active ON special_classification_patterns(is_active);
CREATE INDEX IF NOT EXISTS idx_special_details_material ON special_material_details(material_id);
CREATE INDEX IF NOT EXISTS idx_special_details_drawing_uploaded ON special_material_details(drawing_uploaded);

-- ================================
-- SPECIAL 카테고리 기본 데이터 삽입
-- ================================

-- 기본 SPECIAL 키워드 패턴 삽입
INSERT INTO special_classification_patterns (pattern_type, pattern_value, description, priority) VALUES
('KEYWORD', 'SPECIAL', '영문 SPECIAL 키워드', 1),
('KEYWORD', '스페셜', '한글 스페셜 키워드', 1),
('KEYWORD', 'SPEC', '영문 SPEC 축약어', 2),
('KEYWORD', 'SPL', '영문 SPL 축약어', 2)
ON CONFLICT DO NOTHING;

-- 분류 관련 인덱스 (05_add_classification_columns.sql)
CREATE INDEX IF NOT EXISTS idx_materials_subcategory ON materials(subcategory);
CREATE INDEX IF NOT EXISTS idx_materials_standard ON materials(standard);
CREATE INDEX IF NOT EXISTS idx_materials_grade ON materials(grade);

-- Job 연결 인덱스 (02_modify_files_table.sql)
CREATE INDEX IF NOT EXISTS idx_files_job_no ON files(job_no);

-- 프로젝트 타입 인덱스 (17_add_project_type_column.sql)
CREATE INDEX IF NOT EXISTS idx_jobs_project_type ON jobs(project_type);

-- 사용자 요구사항 테이블 인덱스 (05_create_pipe_details_and_requirements_postgres.sql)
CREATE INDEX IF NOT EXISTS idx_user_requirements_file_id ON user_requirements(file_id);
CREATE INDEX IF NOT EXISTS idx_user_requirements_material_id ON user_requirements(material_id);
CREATE INDEX IF NOT EXISTS idx_user_requirements_status ON user_requirements(status);
CREATE INDEX IF NOT EXISTS idx_user_requirements_type ON user_requirements(requirement_type);

-- ================================
-- 8. 트리거 함수 및 트리거 생성
-- ================================

-- updated_at 자동 업데이트 함수
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ language 'plpgsql';

-- 파이프 끝단 가공 테이블 트리거
CREATE OR REPLACE FUNCTION update_pipe_end_preparations_updated_at()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ language 'plpgsql';

-- 구매 관련 트리거 함수들
CREATE OR REPLACE FUNCTION update_purchase_items_timestamp()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION update_files_updated_at()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ language 'plpgsql';

-- 트리거 적용
CREATE TRIGGER IF NOT EXISTS update_pipe_end_preparations_updated_at BEFORE UPDATE ON pipe_end_preparations
    FOR EACH ROW EXECUTE FUNCTION update_pipe_end_preparations_updated_at();

CREATE TRIGGER IF NOT EXISTS trigger_update_purchase_items_timestamp BEFORE UPDATE ON purchase_items
    FOR EACH ROW EXECUTE FUNCTION update_purchase_items_timestamp();

CREATE TRIGGER IF NOT EXISTS trigger_files_updated_at BEFORE UPDATE ON files
    FOR EACH ROW EXECUTE FUNCTION update_files_updated_at();

-- ================================
-- 해시 생성 함수 및 트리거 (10_add_material_comparison_system.sql)
-- ================================

-- 해시 생성 함수
CREATE OR REPLACE FUNCTION generate_material_hash(
    description TEXT,
    size_spec TEXT DEFAULT '',
    material_grade TEXT DEFAULT ''
) RETURNS VARCHAR(32) AS $$
BEGIN
    -- 정규화: 대소문자 통일, 공백 정리
    description := UPPER(TRIM(REGEXP_REPLACE(description, '\s+', ' ', 'g')));
    size_spec := UPPER(TRIM(COALESCE(size_spec, '')));
    material_grade := UPPER(TRIM(COALESCE(material_grade, '')));
    
    -- MD5 해시 생성 (32자리)
    RETURN MD5(description || '|' || size_spec || '|' || material_grade);
END;
$$ LANGUAGE plpgsql;

-- 자동 해시 생성 트리거 함수
CREATE OR REPLACE FUNCTION auto_generate_material_hash()
RETURNS TRIGGER AS $$
BEGIN
    -- 새로 삽입되거나 업데이트될 때 자동으로 해시 생성
    NEW.material_hash := generate_material_hash(
        NEW.original_description, 
        NEW.size_spec, 
        NEW.material_grade
    );
    NEW.normalized_description := UPPER(TRIM(REGEXP_REPLACE(NEW.original_description, '\s+', ' ', 'g')));
    
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- 자동 해시 생성 트리거 적용
CREATE TRIGGER IF NOT EXISTS trigger_auto_material_hash
    BEFORE INSERT OR UPDATE ON materials
    FOR EACH ROW
    EXECUTE FUNCTION auto_generate_material_hash();

-- ================================
-- 9. 기본 데이터 삽입
-- ================================

-- 기본 프로젝트 생성
INSERT INTO projects (official_project_code, project_name, client_name, status, description) VALUES
('TK-MP-DEV-001', 'TK-MP 개발 프로젝트', 'TK Engineering', 'active', '개발 및 테스트용 프로젝트'),
('TK-MP-DEMO-001', 'TK-MP 데모 프로젝트', 'Demo Client', 'active', '데모 및 시연용 프로젝트'),
('TK-MP-TEST-001', 'TK-MP 테스트 프로젝트', 'Test Client', 'active', '기능 테스트용 프로젝트')
ON CONFLICT (official_project_code) DO NOTHING;

-- Tubing 카테고리 기초 데이터
INSERT INTO tubing_categories (category_code, category_name, description) VALUES
('GENERAL', '일반 Tubing', '일반적인 스테인리스 스틸 튜빙'),
('VCR', 'VCR Tubing', 'VCR (Vacuum Coupling Radiation) 연결용 튜빙'),
('SANITARY', 'Sanitary Tubing', '위생용 튜빙 (식품, 제약 등)'),
('HVAC', 'HVAC Tubing', '공조용 튜빙'),
('HYDRAULIC', 'Hydraulic Tubing', '유압용 튜빙'),
('PNEUMATIC', 'Pneumatic Tubing', '공압용 튜빙'),
('PROCESS', 'Process Tubing', '공정용 특수 튜빙'),
('EXOTIC', 'Exotic Material', '특수 재질 튜빙 (Hastelloy, Inconel 등)')
ON CONFLICT (category_code) DO NOTHING;

-- 주요 제조사 기초 데이터
INSERT INTO tubing_manufacturers (manufacturer_code, manufacturer_name, country) VALUES
('SWAGELOK', 'Swagelok Company', 'USA'),
('PARKER', 'Parker Hannifin', 'USA'),
('HAM_LET', 'Ham-Let Group', 'Israel'),
('SUPERLOK', 'Superlok USA', 'USA'),
('FITOK', 'Fitok Group', 'China'),
('DK_LOK', 'DK-Lok Corporation', 'South Korea'),
('GYROLOK', 'Gyrolok (Oliver Valves)', 'UK'),
('AS_ONE', 'AS ONE Corporation', 'Japan')
ON CONFLICT (manufacturer_code) DO NOTHING;

-- 기본 요구사항 타입 데이터 삽입 (05_create_pipe_details_and_requirements_postgres.sql)
INSERT INTO requirement_types (type_code, type_name, category, description) VALUES
('IMPACT_TEST', '임팩테스트', 'TEST', 'Charpy V-notch, Izod 등의 충격 시험'),
('HEAT_TREATMENT', '열처리', 'TREATMENT', '정규화, 어닐링, 템퍼링 등의 열처리'),
('CERTIFICATION', '인증서', 'CERTIFICATION', '재질증명서, 시험성적서 등'),
('CUSTOM_SPEC', '특수사양', 'CUSTOM', '고객 특별 요구사항'),
('NDT_TEST', '비파괴검사', 'TEST', '초음파, 방사선, 자분탐상 등'),
('CHEMICAL_ANALYSIS', '화학분석', 'TEST', '화학성분 분석'),
('MECHANICAL_TEST', '기계적성질', 'TEST', '인장, 압축, 굽힘 시험'),
('SURFACE_TREATMENT', '표면처리', 'TREATMENT', '도금, 도장, 패시베이션 등'),
('DIMENSIONAL_CHECK', '치수검사', 'INSPECTION', '치수, 형상 검사'),
('WELDING_SPEC', '용접사양', 'SPEC', '용접 방법, 용접재 등')
ON CONFLICT (type_code) DO NOTHING;

-- ================================
-- 10. 뷰 생성
-- ================================

-- 프로젝트 상태 요약 뷰
CREATE OR REPLACE VIEW project_status_view AS
SELECT 
    p.id,
    COALESCE(p.official_project_code, p.design_project_code) as display_code,
    p.project_name,
    p.status,
    COUNT(f.id) as file_count,
    COUNT(m.id) as material_count,
    p.created_at
FROM projects p
LEFT JOIN files f ON p.id = f.project_id AND f.is_active = true
LEFT JOIN materials m ON f.id = m.file_id
GROUP BY p.id, p.official_project_code, p.design_project_code, 
         p.project_name, p.status, p.created_at
ORDER BY p.created_at DESC;

-- ================================
-- 추가 뷰들 (05_add_classification_columns.sql, 10_add_material_comparison_system.sql)
-- ================================

-- 분류 결과 통계 조회용 뷰
CREATE OR REPLACE VIEW classification_summary AS
SELECT 
    f.job_no,
    f.original_filename,
    f.parsed_count,
    f.classification_completed,
    f.classification_timestamp,
    COUNT(*) as total_materials,
    COUNT(CASE WHEN m.classified_category = 'BOLT' THEN 1 END) as bolt_count,
    COUNT(CASE WHEN m.classified_category = 'FLANGE' THEN 1 END) as flange_count,
    COUNT(CASE WHEN m.classified_category = 'FITTING' THEN 1 END) as fitting_count,
    COUNT(CASE WHEN m.classified_category = 'GASKET' THEN 1 END) as gasket_count,
    COUNT(CASE WHEN m.classified_category = 'INSTRUMENT' THEN 1 END) as instrument_count,
    COUNT(CASE WHEN m.classified_category = 'PIPE' THEN 1 END) as pipe_count,
    COUNT(CASE WHEN m.classified_category = 'VALVE' THEN 1 END) as valve_count,
    COUNT(CASE WHEN m.classified_category = 'MATERIAL' THEN 1 END) as material_count,
    COUNT(CASE WHEN m.classified_category = 'OTHER' THEN 1 END) as other_count,
    AVG(m.classification_confidence) as avg_confidence,
    COUNT(CASE WHEN m.is_verified = TRUE THEN 1 END) as verified_count
FROM files f
LEFT JOIN materials m ON f.id = m.file_id
WHERE f.is_active = TRUE
GROUP BY f.id, f.job_no, f.original_filename, f.parsed_count, f.classification_completed, f.classification_timestamp;

-- 분류 성능 통계 뷰
CREATE OR REPLACE VIEW classification_performance AS
SELECT 
    classified_category,
    subcategory,
    standard,
    COUNT(*) as total_count,
    AVG(classification_confidence) as avg_confidence,
    COUNT(CASE WHEN is_verified = TRUE THEN 1 END) as verified_count,
    COUNT(CASE WHEN is_verified = FALSE THEN 1 END) as unverified_count,
    ROUND(
        (COUNT(CASE WHEN is_verified = TRUE THEN 1 END)::DECIMAL / COUNT(*) * 100), 2
    ) as verification_rate
FROM materials
WHERE classified_category IS NOT NULL
GROUP BY classified_category, subcategory, standard
ORDER BY total_count DESC;

-- 누적 재고 현황 뷰 (10_add_material_comparison_system.sql)
CREATE OR REPLACE VIEW material_inventory_status AS
SELECT 
    mpt.job_no,
    mpt.material_hash,
    mpt.description,
    mpt.size_spec,
    mpt.unit,
    
    -- 누적 수량
    SUM(mpt.confirmed_quantity) as total_confirmed,
    SUM(mpt.ordered_quantity) as total_ordered,
    SUM(mpt.received_quantity) as total_received,
    
    -- 현재 가용 재고
    SUM(mpt.received_quantity) as available_stock,
    
    -- 최신 리비전 정보
    MAX(mpt.revision) as latest_revision,
    MAX(mpt.updated_at) as last_updated
    
FROM material_purchase_tracking mpt
WHERE mpt.purchase_status != 'CANCELLED'
GROUP BY mpt.job_no, mpt.material_hash, mpt.description, mpt.size_spec, mpt.unit;

-- ================================
-- 완료 메시지
-- ================================

DO $$
BEGIN
    RAISE NOTICE 'TK-EG BOM 자재관리 데이터베이스 스키마가 성공적으로 생성되었습니다!';
    RAISE NOTICE '생성된 주요 테이블:';
    RAISE NOTICE '   - 기본: projects, files, materials, jobs';
    RAISE NOTICE '   - 자재상세: pipe_details, fitting_details, valve_details, flange_details, bolt_details, gasket_details, instrument_details';
    RAISE NOTICE '   - 파이프: pipe_end_preparations';
    RAISE NOTICE '   - 구매: purchase_items, material_purchase_mapping, material_purchase_tracking';
    RAISE NOTICE '   - 자재규격: material_standards, material_categories, material_specifications, material_grades, material_patterns';
    RAISE NOTICE '   - 특수재질: special_materials, special_material_grades, special_material_patterns';
    RAISE NOTICE '   - 비교시스템: material_revisions_comparison, material_comparison_details';
    RAISE NOTICE '   - Tubing: tubing_categories, tubing_specifications, tubing_manufacturers, tubing_products, material_tubing_mapping';
    RAISE NOTICE '   - 요구사항: requirement_types, user_requirements';
    RAISE NOTICE '   - 로그: user_activity_logs';
    RAISE NOTICE '인증은 SSO(tkuser)에서 처리됩니다.';
END $$;
