"""
ORM-модели для service portal (SQLAlchemy 2.0).

Основные таблицы:
  - users: сотрудники (owner/engineer/technician)
  - customers: клиенты
  - objects: объекты обслуживания
  - tasks/ incidents: задачи и инциденты
  - blog/cases/ideas: контент
"""
from datetime import datetime
from sqlalchemy import (
    Column, Integer, String, Boolean, Text, DateTime, Numeric, Date, BigInteger, SmallInteger, JSON, ForeignKey, CheckConstraint
)
from sqlalchemy.orm import relationship, declarative_base

Base = declarative_base()


class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True, autoincrement=True)
    login = Column(String(50), unique=True, nullable=False)
    password_hash = Column(String(255), nullable=False)
    role = Column(String(20), nullable=False, default="technician")
    full_name = Column(String(255), nullable=False)
    phone = Column(String(50), default="")
    email = Column(String(255), default="")
    max_user_id = Column(BigInteger, nullable=True)
    is_active = Column(Boolean, nullable=False, default=True)
    created_at = Column(DateTime, nullable=False, server_default="NOW()")
    updated_at = Column(DateTime, nullable=False, server_default="NOW()", onupdate="NOW()")

    __table_args__ = (
        CheckConstraint("role IN ('owner','engineer','technician')", name="ck_users_role"),
    )

    objects_created = relationship("Object", foreign_keys="Object.created_by", back_populates="creator")
    tasks_created = relationship("Task", foreign_keys="Task.created_by", back_populates="creator")
    tasks_assigned = relationship("Task", foreign_keys="Task.assigned_to", back_populates="assignee")


class LoginAttempt(Base):
    __tablename__ = "login_attempts"

    id = Column(Integer, primary_key=True, autoincrement=True)
    ip_address = Column(String(45), nullable=False)
    login = Column(String(50), nullable=False, default="")
    attempt_time = Column(DateTime, nullable=False, server_default="NOW()")


class AuditLog(Base):
    __tablename__ = "audit_log"

    id = Column(BigInteger, primary_key=True, autoincrement=True)
    user_id = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"))
    action = Column(String(255), nullable=False)
    details = Column(Text)
    ip_address = Column(String(45), default="")
    created_at = Column(DateTime, nullable=False, server_default="NOW()")


class Customer(Base):
    __tablename__ = "customers"

    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(255), nullable=False)
    inn = Column(String(12), default="")
    kpp = Column(String(9), default="")
    legal_address = Column(String(500), default="")
    contact_person = Column(String(255), default="")
    contact_phone = Column(String(50), default="")
    contact_email = Column(String(255), default="")
    status = Column(String(20), nullable=False, default="active")
    notes = Column(Text)
    created_by = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"))
    created_at = Column(DateTime, nullable=False, server_default="NOW()")
    updated_at = Column(DateTime, nullable=False, server_default="NOW()", onupdate="NOW()")

    __table_args__ = (
        CheckConstraint("status IN ('active','inactive','prospect')", name="ck_customers_status"),
    )

    objects = relationship("Object", back_populates="customer")
    sla_contracts = relationship("SLAContract", back_populates="customer")


class Object(Base):
    __tablename__ = "objects"

    id = Column(Integer, primary_key=True, autoincrement=True)
    customer_id = Column(Integer, ForeignKey("customers.id", ondelete="SET NULL"))
    name = Column(String(255), nullable=False)
    address = Column(String(500), default="")
    object_type = Column(String(100), default="")
    area_sqm = Column(Numeric(10, 2), default=0)
    employees_count = Column(Integer, default=0)
    contact_person = Column(String(255), default="")
    contact_phone = Column(String(50), default="")
    status = Column(String(20), nullable=False, default="active")
    notes = Column(Text)
    risk_score = Column(Numeric(5, 2), default=0)
    complexity_index = Column(Numeric(5, 2), default=0)
    infrastructure_load = Column(Numeric(5, 2), default=0)
    service_history = Column(Numeric(5, 2), default=0)
    object_index = Column(Numeric(5, 2), default=0)
    sla_price_monthly = Column(Numeric(12, 2), default=0)
    region_factor = Column(Numeric(3, 2), default=1.00)
    created_by = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"))
    created_at = Column(DateTime, nullable=False, server_default="NOW()")
    updated_at = Column(DateTime, nullable=False, server_default="NOW()", onupdate="NOW()")

    __table_args__ = (
        CheckConstraint("status IN ('active','inactive','audit','prospective')", name="ck_objects_status"),
    )

    customer = relationship("Customer", back_populates="objects")
    creator = relationship("User", foreign_keys=[created_by], back_populates="objects_created")
    assignments = relationship("ObjectAssignment", back_populates="object")
    tasks = relationship("Task", back_populates="object")
    reports = relationship("Report", back_populates="object")
    incidents = relationship("Incident", back_populates="object")
    sla_contracts = relationship("SLAContract", back_populates="object")
    passports = relationship("ObjectPassport", back_populates="object")


class ObjectAssignment(Base):
    __tablename__ = "object_assignments"

    id = Column(Integer, primary_key=True, autoincrement=True)
    object_id = Column(Integer, ForeignKey("objects.id", ondelete="CASCADE"), nullable=False)
    user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
    role = Column(String(20), nullable=False)
    assigned_at = Column(DateTime, nullable=False, server_default="NOW()")
    unassigned_at = Column(DateTime)

    __table_args__ = (
        CheckConstraint("role IN ('engineer','technician')", name="ck_assignments_role"),
    )

    object = relationship("Object", back_populates="assignments")
    user = relationship("User")


class Task(Base):
    __tablename__ = "tasks"

    id = Column(Integer, primary_key=True, autoincrement=True)
    object_id = Column(Integer, ForeignKey("objects.id", ondelete="CASCADE"), nullable=False)
    assigned_to = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"))
    created_by = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"))
    title = Column(String(500), nullable=False)
    description = Column(Text)
    priority = Column(String(4), nullable=False, default="P3")
    status = Column(String(20), nullable=False, default="open")
    deadline = Column(DateTime)
    sla_remaining_hours = Column(Numeric(6, 1), default=0)
    response_time_minutes = Column(Integer, default=0)
    resolution_time_minutes = Column(Integer, default=0)
    sla_compliant = Column(Boolean)
    checklist_data = Column(JSON)
    result_notes = Column(Text)
    closed_at = Column(DateTime)
    created_at = Column(DateTime, nullable=False, server_default="NOW()")
    updated_at = Column(DateTime, nullable=False, server_default="NOW()", onupdate="NOW()")

    __table_args__ = (
        CheckConstraint("priority IN ('P1','P2','P3','P4')", name="ck_tasks_priority"),
        CheckConstraint("status IN ('open','in_progress','completed','cancelled')", name="ck_tasks_status"),
    )

    object = relationship("Object", back_populates="tasks")
    creator = relationship("User", foreign_keys=[created_by], back_populates="tasks_created")
    assignee = relationship("User", foreign_keys=[assigned_to], back_populates="tasks_assigned")
    comments = relationship("TaskComment", back_populates="task")
    photos = relationship("TaskPhoto", back_populates="task")


class TaskComment(Base):
    __tablename__ = "task_comments"

    id = Column(Integer, primary_key=True, autoincrement=True)
    task_id = Column(Integer, ForeignKey("tasks.id", ondelete="CASCADE"), nullable=False)
    user_id = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"))
    comment = Column(Text, nullable=False)
    created_at = Column(DateTime, nullable=False, server_default="NOW()")

    task = relationship("Task", back_populates="comments")
    user = relationship("User")


class TaskPhoto(Base):
    __tablename__ = "task_photos"

    id = Column(Integer, primary_key=True, autoincrement=True)
    task_id = Column(Integer, ForeignKey("tasks.id", ondelete="SET NULL"))
    report_id = Column(Integer, ForeignKey("reports.id", ondelete="SET NULL"))
    file_path = Column(String(500), nullable=False)
    description = Column(String(500), default="")
    type = Column(String(20), default="other")
    uploaded_by = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"))
    created_at = Column(DateTime, nullable=False, server_default="NOW()")

    __table_args__ = (
        CheckConstraint("type IN ('before','after','evidence','other')", name="ck_photos_type"),
    )

    task = relationship("Task", back_populates="photos")
    uploader = relationship("User")


class Report(Base):
    __tablename__ = "reports"

    id = Column(Integer, primary_key=True, autoincrement=True)
    object_id = Column(Integer, ForeignKey("objects.id", ondelete="CASCADE"), nullable=False)
    created_by = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"))
    report_type = Column(String(20), nullable=False, default="service")
    title = Column(String(500), default="")
    description = Column(Text)
    findings = Column(Text)
    recommendations = Column(Text)
    work_done = Column(Text)
    cause_classification = Column(String(100))
    result_status = Column(String(20), default="ok")
    status = Column(String(20), nullable=False, default="draft")
    client_confirmed = Column(Boolean, default=False)
    created_at = Column(DateTime, nullable=False, server_default="NOW()")
    updated_at = Column(DateTime, nullable=False, server_default="NOW()", onupdate="NOW()")

    __table_args__ = (
        CheckConstraint("report_type IN ('inspection','service','emergency','audit','monthly')", name="ck_reports_type"),
        CheckConstraint("result_status IN ('fixed','partial','revisit','ok')", name="ck_reports_result"),
        CheckConstraint("status IN ('draft','final','cancelled')", name="ck_reports_status"),
    )

    object = relationship("Object", back_populates="reports")
    creator = relationship("User")


class QuestionnaireSession(Base):
    __tablename__ = "questionnaire_sessions"

    id = Column(Integer, primary_key=True, autoincrement=True)
    object_id = Column(Integer, ForeignKey("objects.id", ondelete="SET NULL"))
    client_name = Column(String(255), default="")
    created_by = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"))
    status = Column(String(20), nullable=False, default="draft")
    current_step = Column(SmallInteger, nullable=False, default=1)
    risk_score = Column(Numeric(5, 2), default=0)
    complexity_index = Column(Numeric(5, 2), default=0)
    infrastructure_load = Column(Numeric(5, 2), default=0)
    service_history = Column(Numeric(5, 2), default=0)
    object_index = Column(Numeric(5, 2), default=0)
    sla_price_monthly = Column(Numeric(12, 2), default=0)
    created_at = Column(DateTime, nullable=False, server_default="NOW()")
    updated_at = Column(DateTime, nullable=False, server_default="NOW()", onupdate="NOW()")

    __table_args__ = (
        CheckConstraint("status IN ('draft','completed','cancelled')", name="ck_qsessions_status"),
    )

    answers = relationship("QuestionnaireAnswer", back_populates="session")
    passport = relationship("ObjectPassport", back_populates="session")


class QuestionnaireAnswer(Base):
    __tablename__ = "questionnaire_answers"

    id = Column(Integer, primary_key=True, autoincrement=True)
    session_id = Column(Integer, ForeignKey("questionnaire_sessions.id", ondelete="CASCADE"), nullable=False)
    step = Column(SmallInteger, nullable=False)
    question_key = Column(String(100), nullable=False)
    answer_value = Column(Text)
    created_at = Column(DateTime, nullable=False, server_default="NOW()")

    session = relationship("QuestionnaireSession", back_populates="answers")


class QuestionnaireItem(Base):
    __tablename__ = "questionnaire_items"

    id = Column(Integer, primary_key=True, autoincrement=True)
    step = Column(Integer, nullable=False, default=1)
    section = Column(String(100), nullable=False, default="")
    question_key = Column(String(100), unique=True, nullable=False)
    label = Column(String(255), nullable=False)
    type = Column(String(20), nullable=False, default="text")
    options = Column(JSON)
    required = Column(Boolean, nullable=False, default=False)
    sort_order = Column(Integer, nullable=False, default=0)
    is_active = Column(Boolean, nullable=False, default=True)
    help_text = Column(String(500), default="")
    created_at = Column(DateTime, nullable=False, server_default="NOW()")
    updated_at = Column(DateTime, nullable=False, server_default="NOW()", onupdate="NOW()")

    __table_args__ = (
        CheckConstraint("type IN ('text','number','select','radio','checkbox','textarea')", name="ck_qitems_type"),
    )


class ObjectPassport(Base):
    __tablename__ = "object_passports"

    id = Column(Integer, primary_key=True, autoincrement=True)
    session_id = Column(Integer, ForeignKey("questionnaire_sessions.id", ondelete="SET NULL"))
    object_id = Column(Integer, ForeignKey("objects.id", ondelete="SET NULL"))
    object_index = Column(Numeric(5, 2), default=0)
    risk_score = Column(Numeric(5, 2), default=0)
    complexity_index = Column(Numeric(5, 2), default=0)
    sla_price_monthly = Column(Numeric(12, 2), default=0)
    passport_data = Column(JSON)
    created_by = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"))
    created_at = Column(DateTime, nullable=False, server_default="NOW()")

    session = relationship("QuestionnaireSession", back_populates="passport")
    object = relationship("Object", back_populates="passports")
    creator = relationship("User")


class SLAContract(Base):
    __tablename__ = "sla_contracts"

    id = Column(Integer, primary_key=True, autoincrement=True)
    customer_id = Column(Integer, ForeignKey("customers.id", ondelete="SET NULL"))
    object_id = Column(Integer, ForeignKey("objects.id", ondelete="CASCADE"), nullable=False)
    contract_number = Column(String(50), default="")
    client_name = Column(String(255), default="")
    description = Column(Text)
    start_date = Column(Date, nullable=False)
    end_date = Column(Date)
    sla_price_monthly = Column(Numeric(12, 2), nullable=False, default=0)
    penalty_rate = Column(Numeric(5, 2), default=0)
    response_time_p1 = Column(Integer, default=4)
    response_time_p2 = Column(Integer, default=8)
    response_time_p3 = Column(Integer, default=24)
    response_time_hours = Column(Numeric(5, 1))
    service_level = Column(String(20), nullable=False, default="business")
    status = Column(String(20), nullable=False, default="negotiation")
    created_by = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"))
    created_at = Column(DateTime, nullable=False, server_default="NOW()")
    updated_at = Column(DateTime, nullable=False, server_default="NOW()", onupdate="NOW()")

    __table_args__ = (
        CheckConstraint("service_level IN ('start','business','enterprise')", name="ck_sla_level"),
        CheckConstraint("status IN ('active','expired','cancelled','negotiation')", name="ck_sla_status"),
    )

    customer = relationship("Customer", back_populates="sla_contracts")
    object = relationship("Object", back_populates="sla_contracts")
    creator = relationship("User")


class Incident(Base):
    __tablename__ = "incidents"

    id = Column(Integer, primary_key=True, autoincrement=True)
    object_id = Column(Integer, ForeignKey("objects.id", ondelete="CASCADE"), nullable=False)
    reported_by = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"))
    assigned_to = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"))
    title = Column(String(500), nullable=False)
    description = Column(Text)
    severity = Column(String(4), nullable=False, default="P3")
    status = Column(String(20), nullable=False, default="open")
    resolution = Column(Text)
    cause = Column(String(500), default="")
    resolution_time_minutes = Column(Integer, default=0)
    sla_breached = Column(Boolean, default=False)
    resolved_at = Column(DateTime)
    created_at = Column(DateTime, nullable=False, server_default="NOW()")
    updated_at = Column(DateTime, nullable=False, server_default="NOW()", onupdate="NOW()")

    __table_args__ = (
        CheckConstraint("severity IN ('P1','P2','P3')", name="ck_incidents_severity"),
        CheckConstraint("status IN ('open','in_progress','resolved','closed')", name="ck_incidents_status"),
    )

    object = relationship("Object", back_populates="incidents")
    reporter = relationship("User", foreign_keys=[reported_by])
    assignee = relationship("User", foreign_keys=[assigned_to])


class EngineerKPI(Base):
    __tablename__ = "engineer_kpi"

    id = Column(Integer, primary_key=True, autoincrement=True)
    engineer_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
    period_start = Column(Date, nullable=False)
    period_end = Column(Date, nullable=False)
    sla_compliance = Column(Numeric(5, 2), default=0)
    response_time_score = Column(Numeric(5, 2), default=0)
    resolution_time_score = Column(Numeric(5, 2), default=0)
    diagnosis_accuracy = Column(Numeric(5, 2), default=0)
    reopen_rate = Column(Numeric(5, 2), default=0)
    risk_coverage_score = Column(Numeric(5, 2), default=0)
    documentation_quality = Column(Numeric(5, 2), default=0)
    engineer_score = Column(Numeric(5, 2), default=0)
    grade = Column(String(20), default="")
    components_json = Column(JSON)
    created_at = Column(DateTime, nullable=False, server_default="NOW()")

    engineer = relationship("User")


class SHSRecord(Base):
    __tablename__ = "shs_records"

    id = Column(Integer, primary_key=True, autoincrement=True)
    recorded_by = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"))
    period_start = Column(Date, nullable=False)
    period_end = Column(Date, nullable=False)
    sla_stability = Column(Numeric(5, 2), default=0)
    revenue_stability = Column(Numeric(5, 2), default=0)
    retention = Column(Numeric(5, 2), default=0)
    engineer_performance = Column(Numeric(5, 2), default=0)
    incident_stability = Column(Numeric(5, 2), default=0)
    sales_flow = Column(Numeric(5, 2), default=0)
    operational_efficiency = Column(Numeric(5, 2), default=0)
    shs_score = Column(Numeric(5, 2), default=0)
    shs_status = Column(String(20), default="")
    components_json = Column(JSON)
    created_at = Column(DateTime, nullable=False, server_default="NOW()")

    recorder = relationship("User")


class BlogPost(Base):
    __tablename__ = "blog_posts"

    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(500), nullable=False)
    slug = Column(String(500), unique=True, nullable=False)
    content = Column(Text, nullable=False)
    excerpt = Column(String(1000), default="")
    category = Column(String(50), nullable=False, default="audit")
    author_id = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"))
    status = Column(String(20), nullable=False, default="draft")
    published_at = Column(DateTime)
    created_at = Column(DateTime, nullable=False, server_default="NOW()")
    updated_at = Column(DateTime, nullable=False, server_default="NOW()", onupdate="NOW()")

    __table_args__ = (
        CheckConstraint("category IN ('audit','sla','incident','supervision','documentation','risk','cases')", name="ck_blog_category"),
        CheckConstraint("status IN ('draft','published','archived')", name="ck_blog_status"),
    )

    author = relationship("User")


class FormulaCoefficient(Base):
    __tablename__ = "formula_coefficients"

    id = Column(Integer, primary_key=True, autoincrement=True)
    key = Column(String(100), unique=True, nullable=False)
    value = Column(Numeric(10, 4), nullable=False, default=0)
    description = Column(String(500), default="")
    formula_ref = Column(String(255), default="")
    is_active = Column(Boolean, nullable=False, default=True)
    updated_by = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"))
    updated_at = Column(DateTime, nullable=False, server_default="NOW()", onupdate="NOW()")

    updater = relationship("User")


class Case(Base):
    __tablename__ = "cases"

    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(500), nullable=False)
    text = Column(Text, nullable=False)
    effect = Column(Text, nullable=False)
    sort_order = Column(Integer, nullable=False, default=0)
    is_active = Column(Boolean, nullable=False, default=True)
    created_at = Column(DateTime, nullable=False, server_default="NOW()")
    updated_at = Column(DateTime, nullable=False, server_default="NOW()", onupdate="NOW()")


class Idea(Base):
    __tablename__ = "ideas"

    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(500), nullable=False)
    description = Column(Text, default="")
    status = Column(String(20), nullable=False, default="normal")
    created_by = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"))
    created_at = Column(DateTime, nullable=False, server_default="NOW()")
    updated_at = Column(DateTime, nullable=False, server_default="NOW()", onupdate="NOW()")

    __table_args__ = (
        CheckConstraint("status IN ('normal','in_progress','completed')", name="ck_ideas_status"),
    )

    creator = relationship("User")


class QuickMenuItem(Base):
    __tablename__ = "quick_menu_items"

    id = Column(Integer, primary_key=True, autoincrement=True)
    role = Column(String(20), nullable=False)
    label = Column(String(100), nullable=False)
    url = Column(String(500), nullable=False)
    sort_order = Column(Integer, nullable=False, default=0)
    created_by = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"))
    updated_at = Column(DateTime, nullable=False, server_default="NOW()", onupdate="NOW()")

    creator = relationship("User")


class RoleMenuPermission(Base):
    __tablename__ = "role_menu_permissions"

    id = Column(Integer, primary_key=True, autoincrement=True)
    role = Column(String(20), nullable=False)
    menu_key = Column(String(50), nullable=False)
    visible = Column(Boolean, nullable=False, default=True)

    __table_args__ = (
        CheckConstraint("role IN ('engineer','technician')", name="ck_role_menu_role"),
    )



