from sqlalchemy import Column, Integer, String, Boolean, DateTime, Text, Numeric, ForeignKey, JSON
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from datetime import datetime

Base = declarative_base()

class Project(Base):
    __tablename__ = "projects"
    
    id = Column(Integer, primary_key=True, index=True)
    official_project_code = Column(String(50), unique=True, index=True)
    project_name = Column(String(200), nullable=False)
    client_name = Column(String(100))
    design_project_code = Column(String(50))
    design_project_name = Column(String(200))
    is_code_matched = Column(Boolean, default=False)
    matched_by = Column(String(100))
    matched_at = Column(DateTime)
    status = Column(String(20), default='active')
    created_at = Column(DateTime, default=datetime.utcnow)
    updated_at = Column(DateTime, default=datetime.utcnow)
    description = Column(Text)
    notes = Column(Text)
    
    # 관계 설정
    files = relationship("File", back_populates="project")

class File(Base):
    __tablename__ = "files"
    
    id = Column(Integer, primary_key=True, index=True)
    project_id = Column(Integer, ForeignKey("projects.id"))
    filename = Column(String(255), nullable=False)
    original_filename = Column(String(255), nullable=False)
    file_path = Column(String(500), nullable=False)
    revision = Column(String(20), default='Rev.0')
    upload_date = Column(DateTime, default=datetime.utcnow)
    uploaded_by = Column(String(100))
    file_type = Column(String(10))
    file_size = Column(Integer)
    is_active = Column(Boolean, default=True)
    
    # 관계 설정
    project = relationship("Project", back_populates="files")
    materials = relationship("Material", back_populates="file")

class Material(Base):
    __tablename__ = "materials"
    
    id = Column(Integer, primary_key=True, index=True)
    file_id = Column(Integer, ForeignKey("files.id"))
    line_number = Column(Integer)
    original_description = Column(Text, nullable=False)
    classified_category = Column(String(50))
    classified_subcategory = Column(String(100))
    material_grade = Column(String(50))
    schedule = Column(String(20))
    size_spec = Column(String(50))
    quantity = Column(Numeric(10, 3), nullable=False)
    unit = Column(String(10), nullable=False)
    # length = Column(Numeric(10, 3))  # 임시로 주석 처리
    drawing_name = Column(String(100))
    area_code = Column(String(20))
    line_no = Column(String(50))
    classification_confidence = Column(Numeric(3, 2))
    is_verified = Column(Boolean, default=False)
    verified_by = Column(String(50))
    verified_at = Column(DateTime)
    drawing_reference = Column(String(100))
    notes = Column(Text)
    created_at = Column(DateTime, default=datetime.utcnow)
    is_active = Column(Boolean, default=True)
    
    # 추가 필드들
    main_nom = Column(String(50))
    red_nom = Column(String(50))
    purchase_confirmed = Column(Boolean, default=False)
    purchase_confirmed_at = Column(DateTime)
    purchase_status = Column(String(20), default='not_purchased')
    purchase_confirmed_by = Column(String(100))
    confirmed_quantity = Column(Numeric(10, 3))
    revision_status = Column(String(20), default='active')
    material_hash = Column(String(100))
    normalized_description = Column(Text)
    full_material_grade = Column(String(100))
    row_number = Column(Integer)
    length = Column(Numeric(10, 3))
    brand = Column(String(100))
    user_requirement = Column(Text)
    total_length = Column(Numeric(10, 3))
    
    # 관계 설정
    file = relationship("File", back_populates="materials")

# ========== 자재 규격/재질 기준표 테이블들 ==========

class MaterialStandard(Base):
    """자재 규격 표준 (ASTM, KS, JIS 등)"""
    __tablename__ = "material_standards"
    
    id = Column(Integer, primary_key=True, index=True)
    standard_code = Column(String(20), unique=True, nullable=False, index=True)  # ASTM_ASME, KS, JIS
    standard_name = Column(String(100), nullable=False)  # 미국재질학회, 한국산업표준, 일본공업규격
    description = Column(Text)
    country = Column(String(50))  # USA, KOREA, JAPAN
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, default=datetime.utcnow)
    updated_at = Column(DateTime, default=datetime.utcnow)
    
    # 관계 설정
    categories = relationship("MaterialCategory", back_populates="standard")

class MaterialCategory(Base):
    """제조방식별 카테고리 (FORGED, WELDED, CAST 등)"""
    __tablename__ = "material_categories"
    
    id = Column(Integer, primary_key=True, index=True)
    standard_id = Column(Integer, ForeignKey("material_standards.id"))
    category_code = Column(String(50), nullable=False)  # FORGED_GRADES, WELDED_GRADES, CAST_GRADES
    category_name = Column(String(100), nullable=False)  # 단조품, 용접품, 주조품
    description = Column(Text)
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, default=datetime.utcnow)
    updated_at = Column(DateTime, default=datetime.utcnow)
    
    # 관계 설정
    standard = relationship("MaterialStandard", back_populates="categories")
    specifications = relationship("MaterialSpecification", back_populates="category")

class MaterialSpecification(Base):
    """구체적인 규격 (A182, A105, D3507 등)"""
    __tablename__ = "material_specifications"
    
    id = Column(Integer, primary_key=True, index=True)
    category_id = Column(Integer, ForeignKey("material_categories.id"))
    spec_code = Column(String(20), nullable=False)  # A182, A105, D3507
    spec_name = Column(String(100), nullable=False)  # 탄소강 단조품, 배관용 탄소강관
    description = Column(Text)
    material_type = Column(String(50))  # carbon_alloy, stainless, carbon
    manufacturing = Column(String(50))  # FORGED, WELDED_FABRICATED, CAST, SEAMLESS
    pressure_rating = Column(String(100))  # 150LB ~ 9000LB
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, default=datetime.utcnow)
    updated_at = Column(DateTime, default=datetime.utcnow)
    
    # 관계 설정
    category = relationship("MaterialCategory", back_populates="specifications")
    grades = relationship("MaterialGrade", back_populates="specification")
    patterns = relationship("MaterialPattern", back_populates="specification")

class MaterialGrade(Base):
    """등급별 상세 정보 (F1, F5, WPA, WPB 등)"""
    __tablename__ = "material_grades"
    
    id = Column(Integer, primary_key=True, index=True)
    specification_id = Column(Integer, ForeignKey("material_specifications.id"))
    grade_code = Column(String(20), nullable=False)  # F1, F5, WPA, WPB
    grade_name = Column(String(100))
    composition = Column(String(200))  # 0.5Mo, 5Cr-0.5Mo, 18Cr-8Ni
    applications = Column(String(200))  # 중온용, 고온용, 저압용
    temp_max = Column(String(50))  # 482°C, 649°C
    temp_range = Column(String(100))  # -29°C ~ 400°C
    yield_strength = Column(String(50))  # 30 ksi, 35 ksi
    tensile_strength = Column(String(50))
    corrosion_resistance = Column(String(50))  # 보통, 우수
    stabilizer = Column(String(50))  # Titanium, Niobium
    base_grade = Column(String(20))  # 304, 316
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, default=datetime.utcnow)
    updated_at = Column(DateTime, default=datetime.utcnow)
    
    # 관계 설정
    specification = relationship("MaterialSpecification", back_populates="grades")

class MaterialPattern(Base):
    """정규식 패턴들"""
    __tablename__ = "material_patterns"
    
    id = Column(Integer, primary_key=True, index=True)
    specification_id = Column(Integer, ForeignKey("material_specifications.id"))
    pattern = Column(Text, nullable=False)  # 정규식 패턴
    description = Column(String(200))
    priority = Column(Integer, default=1)  # 패턴 우선순위
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, default=datetime.utcnow)
    updated_at = Column(DateTime, default=datetime.utcnow)
    
    # 관계 설정
    specification = relationship("MaterialSpecification", back_populates="patterns")

class SpecialMaterial(Base):
    """특수 재질 (INCONEL, HASTELLOY, TITANIUM 등)"""
    __tablename__ = "special_materials"
    
    id = Column(Integer, primary_key=True, index=True)
    material_type = Column(String(50), nullable=False)  # SUPER_ALLOYS, TITANIUM, COPPER_ALLOYS
    material_name = Column(String(100), nullable=False)  # INCONEL, HASTELLOY, TITANIUM
    description = Column(Text)
    composition = Column(String(200))
    applications = Column(Text)
    temp_max = Column(String(50))
    manufacturing = Column(String(50))
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, default=datetime.utcnow)
    updated_at = Column(DateTime, default=datetime.utcnow)
    
    # 관계 설정
    grades = relationship("SpecialMaterialGrade", back_populates="material")
    patterns = relationship("SpecialMaterialPattern", back_populates="material")

class SpecialMaterialGrade(Base):
    """특수 재질 등급"""
    __tablename__ = "special_material_grades"
    
    id = Column(Integer, primary_key=True, index=True)
    material_id = Column(Integer, ForeignKey("special_materials.id"))
    grade_code = Column(String(20), nullable=False)  # 600, 625, C276
    composition = Column(String(200))
    applications = Column(String(200))
    temp_max = Column(String(50))
    strength = Column(String(50))
    purity = Column(String(100))
    corrosion = Column(String(50))
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, default=datetime.utcnow)
    updated_at = Column(DateTime, default=datetime.utcnow)
    
    # 관계 설정
    material = relationship("SpecialMaterial", back_populates="grades")

class SpecialMaterialPattern(Base):
    """특수 재질 정규식 패턴"""
    __tablename__ = "special_material_patterns"
    
    id = Column(Integer, primary_key=True, index=True)
    material_id = Column(Integer, ForeignKey("special_materials.id"))
    pattern = Column(Text, nullable=False)
    description = Column(String(200))
    priority = Column(Integer, default=1)
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, default=datetime.utcnow)
    updated_at = Column(DateTime, default=datetime.utcnow)
    
    # 관계 설정
    material = relationship("SpecialMaterial", back_populates="patterns")

# ========== 파이프 상세 정보 및 사용자 요구사항 테이블 ==========

class PipeDetail(Base):
    """파이프 상세 정보"""
    __tablename__ = "pipe_details"
    
    id = Column(Integer, primary_key=True, index=True)
    file_id = Column(Integer, ForeignKey("files.id"), nullable=False)
    
    # 재질 정보
    material_standard = Column(String(50))  # ASTM, KS, JIS 등
    material_grade = Column(String(50))     # A106, A53, STPG370 등
    material_type = Column(String(50))      # CARBON, STAINLESS 등
    
    # 파이프 특화 정보
    manufacturing_method = Column(String(50))  # SEAMLESS, WELDED, CAST
    end_preparation = Column(String(50))      # BOTH_ENDS_BEVELED, ONE_END_BEVELED, NO_BEVEL
    schedule = Column(String(50))             # SCH 10, 20, 40, 80 등
    wall_thickness = Column(String(50))       # 벽두께 정보
    
    # 치수 정보
    nominal_size = Column(String(50))         # MAIN_NOM (인치, 직경)
    length_mm = Column(Numeric(10, 3))       # LENGTH (길이)
    
    # 신뢰도
    material_confidence = Column(Numeric(3, 2))
    manufacturing_confidence = Column(Numeric(3, 2))
    end_prep_confidence = Column(Numeric(3, 2))
    schedule_confidence = Column(Numeric(3, 2))
    
    # 메타데이터
    created_at = Column(DateTime, default=datetime.utcnow)
    updated_at = Column(DateTime, default=datetime.utcnow)
    
    # 관계 설정
    file = relationship("File", backref="pipe_details")

class RequirementType(Base):
    """요구사항 타입 마스터"""
    __tablename__ = "requirement_types"
    
    id = Column(Integer, primary_key=True, index=True)
    type_code = Column(String(50), unique=True, nullable=False)    # 'IMPACT_TEST', 'HEAT_TREATMENT' 등
    type_name = Column(String(100), nullable=False)               # '임팩테스트', '열처리' 등
    category = Column(String(50), nullable=False)                 # 'TEST', 'TREATMENT', 'CERTIFICATION', 'CUSTOM' 등
    description = Column(Text)                                    # 타입 설명
    is_active = Column(Boolean, default=True)
    
    created_at = Column(DateTime, default=datetime.utcnow)
    
    # 관계 설정은 문자열 기반이므로 제거

class UserRequirement(Base):
    """사용자 추가 요구사항"""
    __tablename__ = "user_requirements"
    
    id = Column(Integer, primary_key=True, index=True)
    file_id = Column(Integer, ForeignKey("files.id"), nullable=False)
    material_id = Column(Integer, ForeignKey("materials.id"), nullable=True)  # 자재 ID (개별 자재별 요구사항 연결)
    
    # 요구사항 타입
    requirement_type = Column(String(50), nullable=False)     # 'IMPACT_TEST', 'HEAT_TREATMENT', 'CUSTOM_SPEC', 'CERTIFICATION' 등
    
    # 요구사항 내용
    requirement_title = Column(String(200), nullable=False)    # '임팩테스트', '열처리', '인증서' 등
    requirement_description = Column(Text)                     # 상세 설명
    requirement_spec = Column(Text)                           # 구체적 스펙 (예: "Charpy V-notch -20°C")
    
    # 상태 관리
    status = Column(String(20), default='PENDING')           # 'PENDING', 'IN_PROGRESS', 'COMPLETED', 'CANCELLED'
    priority = Column(String(20), default='NORMAL')          # 'LOW', 'NORMAL', 'HIGH', 'URGENT'
    
    # 담당자 정보
    assigned_to = Column(String(100))                        # 담당자명
    due_date = Column(DateTime)                              # 완료 예정일
    
    # 메타데이터
    created_at = Column(DateTime, default=datetime.utcnow)
    updated_at = Column(DateTime, default=datetime.utcnow)
    
    # 관계 설정
    file = relationship("File", backref="user_requirements")

# ========== Tubing 시스템 모델들 ==========

class TubingCategory(Base):
    """Tubing 카테고리 (일반, VCR, 위생용 등)"""
    __tablename__ = "tubing_categories"
    
    id = Column(Integer, primary_key=True, index=True)
    category_code = Column(String(20), unique=True, nullable=False)
    category_name = Column(String(100), nullable=False)
    description = Column(Text)
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, default=datetime.utcnow)
    updated_at = Column(DateTime, default=datetime.utcnow)
    
    # 관계 설정
    specifications = relationship("TubingSpecification", back_populates="category")

class TubingSpecification(Base):
    """Tubing 규격 마스터"""
    __tablename__ = "tubing_specifications"
    
    id = Column(Integer, primary_key=True, index=True)
    category_id = Column(Integer, ForeignKey("tubing_categories.id"))
    spec_code = Column(String(50), unique=True, nullable=False)
    spec_name = Column(String(200), nullable=False)
    
    # 물리적 규격
    outer_diameter_mm = Column(Numeric(8, 3))
    wall_thickness_mm = Column(Numeric(6, 3))
    inner_diameter_mm = Column(Numeric(8, 3))
    
    # 재질 정보
    material_grade = Column(String(100))
    material_standard = Column(String(100))
    
    # 압력/온도 등급
    max_pressure_bar = Column(Numeric(8, 2))
    max_temperature_c = Column(Numeric(6, 2))
    min_temperature_c = Column(Numeric(6, 2))
    
    # 표준 규격
    standard_length_m = Column(Numeric(8, 3))
    bend_radius_min_mm = Column(Numeric(8, 2))
    
    # 기타 정보
    surface_finish = Column(String(100))
    hardness = Column(String(50))
    notes = Column(Text)
    
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, default=datetime.utcnow)
    updated_at = Column(DateTime, default=datetime.utcnow)
    
    # 관계 설정
    category = relationship("TubingCategory", back_populates="specifications")
    products = relationship("TubingProduct", back_populates="specification")

class TubingManufacturer(Base):
    """Tubing 제조사"""
    __tablename__ = "tubing_manufacturers"
    
    id = Column(Integer, primary_key=True, index=True)
    manufacturer_code = Column(String(20), unique=True, nullable=False)
    manufacturer_name = Column(String(200), nullable=False)
    country = Column(String(100))
    website = Column(String(500))
    contact_info = Column(JSON)  # JSONB 타입
    quality_certs = Column(JSON)  # JSONB 타입
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, default=datetime.utcnow)
    updated_at = Column(DateTime, default=datetime.utcnow)
    
    # 관계 설정
    products = relationship("TubingProduct", back_populates="manufacturer")

class TubingProduct(Base):
    """제조사별 Tubing 제품 (품목번호 매핑)"""
    __tablename__ = "tubing_products"
    
    id = Column(Integer, primary_key=True, index=True)
    specification_id = Column(Integer, ForeignKey("tubing_specifications.id"))
    manufacturer_id = Column(Integer, ForeignKey("tubing_manufacturers.id"))
    
    # 제조사 품목번호 정보
    manufacturer_part_number = Column(String(200), nullable=False)
    manufacturer_product_name = Column(String(300))
    
    # 가격/공급 정보
    list_price = Column(Numeric(12, 2))
    currency = Column(String(10), default='KRW')
    lead_time_days = Column(Integer)
    minimum_order_qty = Column(Numeric(10, 3))
    standard_packaging_qty = Column(Numeric(10, 3))
    
    # 가용성 정보
    availability_status = Column(String(50))
    last_price_update = Column(DateTime)
    
    # 추가 정보
    datasheet_url = Column(String(500))
    catalog_page = Column(String(100))
    notes = Column(Text)
    
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, default=datetime.utcnow)
    updated_at = Column(DateTime, default=datetime.utcnow)
    
    # 관계 설정
    specification = relationship("TubingSpecification", back_populates="products")
    manufacturer = relationship("TubingManufacturer", back_populates="products")
    material_mappings = relationship("MaterialTubingMapping", back_populates="tubing_product")

class MaterialTubingMapping(Base):
    """BOM 자재와 Tubing 제품 매핑"""
    __tablename__ = "material_tubing_mapping"
    
    id = Column(Integer, primary_key=True, index=True)
    material_id = Column(Integer, ForeignKey("materials.id", ondelete="CASCADE"))
    tubing_product_id = Column(Integer, ForeignKey("tubing_products.id"))
    
    # 매핑 정보
    confidence_score = Column(Numeric(3, 2))
    mapping_method = Column(String(50))
    mapped_by = Column(String(100))
    mapped_at = Column(DateTime, default=datetime.utcnow)
    
    # 수량 정보
    required_length_m = Column(Numeric(10, 3))
    calculated_quantity = Column(Numeric(10, 3))
    
    # 검증 정보
    is_verified = Column(Boolean, default=False)
    verified_by = Column(String(100))
    verified_at = Column(DateTime)
    
    notes = Column(Text)
    created_at = Column(DateTime, default=datetime.utcnow)
    
    # 관계 설정
    material = relationship("Material", backref="tubing_mappings")
    tubing_product = relationship("TubingProduct", back_populates="material_mappings")
