from __future__ import annotations

from sqlalchemy import JSON, BigInteger, Boolean, Date, DateTime, DECIMAL, ForeignKey, Index, Integer, String, Text, text
from sqlalchemy.orm import Mapped, mapped_column

from app.models.base import Base


class MiniAppAttendancePoint(Base):
    __tablename__ = "attendance_points"

    name: Mapped[str] = mapped_column(String(128), primary_key=True)
    latitude: Mapped[float | None] = mapped_column(DECIMAL(10, 7), nullable=True)
    longitude: Mapped[float | None] = mapped_column(DECIMAL(10, 7), nullable=True)
    radius_meters: Mapped[int] = mapped_column(Integer, server_default=text("500"))
    day_start: Mapped[str] = mapped_column(String(5), server_default=text("'08:00'"))
    day_end: Mapped[str] = mapped_column(String(5), server_default=text("'17:20'"))
    lunch_start: Mapped[str] = mapped_column(String(5), server_default=text("'11:40'"))
    lunch_end: Mapped[str] = mapped_column(String(5), server_default=text("'12:40'"))
    dinner_start: Mapped[str] = mapped_column(String(5), server_default=text("'17:20'"))
    dinner_end: Mapped[str] = mapped_column(String(5), server_default=text("'18:00'"))
    overtime_start: Mapped[str] = mapped_column(String(5), server_default=text("'18:00'"))
    overtime_end: Mapped[str] = mapped_column(String(5), server_default=text("'20:00'"))
    night_start: Mapped[str] = mapped_column(String(5), server_default=text("'20:00'"))
    night_end: Mapped[str] = mapped_column(String(5), server_default=text("'06:00'"))
    remark: Mapped[str | None] = mapped_column(String(500), nullable=True)
    is_active: Mapped[bool] = mapped_column(Boolean, server_default=text("1"))
    created_at: Mapped[object] = mapped_column(DateTime)
    updated_at: Mapped[object] = mapped_column(DateTime)


class MiniAppPersonnel(Base):
    __tablename__ = "personnel"

    phone: Mapped[str] = mapped_column(String(20), primary_key=True)
    name: Mapped[str] = mapped_column(String(64))
    is_temporary: Mapped[bool] = mapped_column(Boolean, server_default=text("0"))
    temporary_expires_at: Mapped[object | None] = mapped_column(DateTime, nullable=True)
    created_at: Mapped[object] = mapped_column(DateTime)
    updated_at: Mapped[object] = mapped_column(DateTime)


class MiniAppPersonRole(Base):
    __tablename__ = "person_roles"

    phone: Mapped[str] = mapped_column(ForeignKey("personnel.phone"), primary_key=True)
    role: Mapped[str] = mapped_column(String(32), primary_key=True)
    created_at: Mapped[object] = mapped_column(DateTime)


class MiniAppPersonAttendancePoint(Base):
    __tablename__ = "person_attendance_points"

    phone: Mapped[str] = mapped_column(ForeignKey("personnel.phone"), primary_key=True)
    attendance_point_name: Mapped[str] = mapped_column(ForeignKey("attendance_points.name"), primary_key=True)
    created_at: Mapped[object] = mapped_column(DateTime)


class MiniAppProduct(Base):
    __tablename__ = "products"

    attendance_point_name: Mapped[str] = mapped_column(String(128), primary_key=True, server_default=text("''"))
    project_no: Mapped[str] = mapped_column(String(64), primary_key=True)
    product_name: Mapped[str] = mapped_column(String(255), primary_key=True)
    device_no: Mapped[str] = mapped_column(String(64), primary_key=True)
    process_name: Mapped[str] = mapped_column(String(128), primary_key=True)
    profile_no: Mapped[str | None] = mapped_column(String(128), nullable=True)
    material_code: Mapped[str | None] = mapped_column(String(128), nullable=True)
    material_name: Mapped[str | None] = mapped_column(String(255), nullable=True)
    supplier: Mapped[str | None] = mapped_column(String(255), nullable=True)
    product_net_weight_kg: Mapped[float | None] = mapped_column(DECIMAL(12, 4), nullable=True)
    product_gross_weight_kg: Mapped[float | None] = mapped_column(DECIMAL(12, 4), nullable=True)
    scrap_loss_rate: Mapped[float | None] = mapped_column(DECIMAL(10, 6), nullable=True)
    waste_price_yuan_per_kg: Mapped[float | None] = mapped_column(DECIMAL(12, 4), nullable=True)
    stamping_method: Mapped[str | None] = mapped_column(String(128), nullable=True)
    operator_count: Mapped[float] = mapped_column(DECIMAL(10, 2), server_default=text("1"))
    process_unit_price_yuan: Mapped[float] = mapped_column(DECIMAL(12, 4), server_default=text("0"))
    standard_beat: Mapped[float] = mapped_column(DECIMAL(12, 3), server_default=text("0"))
    standard_workload: Mapped[float] = mapped_column(DECIMAL(12, 2), server_default=text("0"))
    created_at: Mapped[object] = mapped_column(DateTime)
    updated_at: Mapped[object] = mapped_column(DateTime)

    __table_args__ = (
        Index("idx_products_device_no", "device_no"),
        Index("idx_products_material_code", "material_code"),
    )


class MiniAppEquipment(Base):
    __tablename__ = "equipment"

    attendance_point_name: Mapped[str] = mapped_column(String(128), primary_key=True, server_default=text("''"))
    device_no: Mapped[str] = mapped_column(String(64), primary_key=True)
    device_type: Mapped[str] = mapped_column(String(32), server_default=text("'冲压设备'"))
    remark: Mapped[str | None] = mapped_column(String(500), nullable=True)
    created_at: Mapped[object] = mapped_column(DateTime)
    updated_at: Mapped[object] = mapped_column(DateTime)


class MiniAppWorkSchedule(Base):
    __tablename__ = "work_schedules"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, server_default=text("1"))
    day_start: Mapped[str] = mapped_column(String(5), server_default=text("'08:00'"))
    day_end: Mapped[str] = mapped_column(String(5), server_default=text("'17:20'"))
    lunch_start: Mapped[str] = mapped_column(String(5), server_default=text("'11:40'"))
    lunch_end: Mapped[str] = mapped_column(String(5), server_default=text("'12:40'"))
    dinner_start: Mapped[str] = mapped_column(String(5), server_default=text("'17:20'"))
    dinner_end: Mapped[str] = mapped_column(String(5), server_default=text("'18:00'"))
    overtime_start: Mapped[str] = mapped_column(String(5), server_default=text("'18:00'"))
    overtime_end: Mapped[str] = mapped_column(String(5), server_default=text("'20:00'"))
    night_start: Mapped[str] = mapped_column(String(5), server_default=text("'20:00'"))
    night_end: Mapped[str] = mapped_column(String(5), server_default=text("'06:00'"))
    attendance_latitude: Mapped[float | None] = mapped_column(DECIMAL(10, 7), nullable=True)
    attendance_longitude: Mapped[float | None] = mapped_column(DECIMAL(10, 7), nullable=True)
    attendance_radius_meters: Mapped[int] = mapped_column(Integer, server_default=text("500"))
    auto_submit_hours: Mapped[float] = mapped_column(DECIMAL(10, 2), server_default=text("15"))
    updated_by: Mapped[str | None] = mapped_column(String(20), nullable=True)
    created_at: Mapped[object] = mapped_column(DateTime)
    updated_at: Mapped[object] = mapped_column(DateTime)


class MiniAppWorkSession(Base):
    __tablename__ = "work_sessions"

    id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
    attendance_point_name: Mapped[str] = mapped_column(String(128), server_default=text("''"))
    employee_phone: Mapped[str] = mapped_column(ForeignKey("personnel.phone"))
    start_at: Mapped[object] = mapped_column(DateTime)
    end_at: Mapped[object | None] = mapped_column(DateTime, nullable=True)
    status: Mapped[str] = mapped_column(String(32), server_default=text("'active'"))
    created_at: Mapped[object] = mapped_column(DateTime)
    updated_at: Mapped[object] = mapped_column(DateTime)

    __table_args__ = (
        Index("idx_sessions_employee_status", "employee_phone", "status"),
    )


class MiniAppWorkSessionDevice(Base):
    __tablename__ = "work_session_devices"

    id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
    session_id: Mapped[int] = mapped_column(ForeignKey("work_sessions.id"))
    attendance_point_name: Mapped[str] = mapped_column(String(128), server_default=text("''"))
    device_no: Mapped[str] = mapped_column(String(255))
    process_name: Mapped[str] = mapped_column(String(128), server_default=text("''"))
    scanned_at: Mapped[object] = mapped_column(DateTime)
    sort_order: Mapped[int] = mapped_column(Integer, server_default=text("0"))
    released_at: Mapped[object | None] = mapped_column(DateTime, nullable=True)
    released_by: Mapped[str | None] = mapped_column(String(20), nullable=True)
    release_reason: Mapped[str | None] = mapped_column(String(120), nullable=True)

    __table_args__ = (
        Index("idx_session_devices_session", "session_id"),
        Index("idx_session_devices_device", "device_no"),
        Index("idx_session_devices_release", "released_at"),
    )


class MiniAppProductionReport(Base):
    __tablename__ = "production_reports"

    id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
    attendance_point_name: Mapped[str] = mapped_column(String(128), server_default=text("''"))
    session_id: Mapped[int] = mapped_column(ForeignKey("work_sessions.id"), unique=True)
    employee_phone: Mapped[str] = mapped_column(ForeignKey("personnel.phone"))
    report_date: Mapped[object] = mapped_column(Date)
    start_at: Mapped[object] = mapped_column(DateTime)
    end_at: Mapped[object] = mapped_column(DateTime)
    duration_minutes: Mapped[float] = mapped_column(DECIMAL(10, 2), server_default=text("0"))
    break_minutes: Mapped[float] = mapped_column(DECIMAL(10, 2), server_default=text("0"))
    effective_minutes: Mapped[float] = mapped_column(DECIMAL(10, 2), server_default=text("0"))
    total_good_qty: Mapped[float] = mapped_column(DECIMAL(12, 2), server_default=text("0"))
    total_output_qty: Mapped[float] = mapped_column(DECIMAL(12, 2), server_default=text("0"))
    actual_beat: Mapped[float] = mapped_column(DECIMAL(12, 3), server_default=text("0"))
    standard_beat: Mapped[float] = mapped_column(DECIMAL(12, 3), server_default=text("0"))
    expected_workload: Mapped[float] = mapped_column(DECIMAL(12, 2), server_default=text("0"))
    pace_rate: Mapped[float] = mapped_column(DECIMAL(10, 2), server_default=text("0"))
    workload_rate: Mapped[float] = mapped_column(DECIMAL(10, 2), server_default=text("0"))
    status: Mapped[str] = mapped_column(String(32), server_default=text("'pending'"))
    reviewer_phone: Mapped[str | None] = mapped_column(String(20), nullable=True)
    reviewed_at: Mapped[object | None] = mapped_column(DateTime, nullable=True)
    reject_reason: Mapped[str | None] = mapped_column(String(500), nullable=True)
    review_remark: Mapped[str | None] = mapped_column(String(500), nullable=True)
    submitted_at: Mapped[object] = mapped_column(DateTime)
    is_system_auto_submitted: Mapped[bool] = mapped_column(Boolean, server_default=text("0"))
    auto_submit_reason: Mapped[str | None] = mapped_column(String(120), nullable=True)
    is_multi_person_assistant: Mapped[bool] = mapped_column(Boolean, server_default=text("0"))
    multi_person_source_report_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    is_voided: Mapped[bool] = mapped_column(Boolean, server_default=text("0"))
    voided_at: Mapped[object | None] = mapped_column(DateTime, nullable=True)
    voided_by: Mapped[str | None] = mapped_column(ForeignKey("personnel.phone"), nullable=True)
    unvoid_deadline_at: Mapped[object | None] = mapped_column(DateTime, nullable=True)
    updated_at: Mapped[object] = mapped_column(DateTime)

    __table_args__ = (
        Index("idx_reports_employee_date", "employee_phone", "report_date"),
        Index("idx_reports_status_date", "status", "report_date"),
        Index("idx_reports_reviewer", "reviewer_phone", "reviewed_at"),
        Index("idx_reports_voided", "is_voided", "voided_at"),
    )


class MiniAppProductionReportItem(Base):
    __tablename__ = "production_report_items"

    id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
    report_id: Mapped[int] = mapped_column(ForeignKey("production_reports.id"))
    attendance_point_name: Mapped[str] = mapped_column(String(128), server_default=text("''"))
    device_no: Mapped[str] = mapped_column(String(64))
    project_no: Mapped[str] = mapped_column(String(64))
    product_name: Mapped[str] = mapped_column(String(255))
    material_code: Mapped[str | None] = mapped_column(String(128), nullable=True)
    material_name: Mapped[str | None] = mapped_column(String(255), nullable=True)
    raw_material_batch_no: Mapped[str | None] = mapped_column(String(128), nullable=True)
    process_name: Mapped[str | None] = mapped_column(String(128), nullable=True)
    stamping_method: Mapped[str | None] = mapped_column(String(128), nullable=True)
    operator_count: Mapped[float] = mapped_column(DECIMAL(10, 2), server_default=text("1"))
    process_unit_price_yuan: Mapped[float] = mapped_column(DECIMAL(12, 4), server_default=text("0"))
    standard_beat: Mapped[float] = mapped_column(DECIMAL(12, 3), server_default=text("0"))
    standard_workload: Mapped[float] = mapped_column(DECIMAL(12, 2), server_default=text("0"))
    good_qty: Mapped[float] = mapped_column(DECIMAL(12, 2), server_default=text("0"))
    defect_qty: Mapped[float] = mapped_column(DECIMAL(12, 2), server_default=text("0"))
    scrap_qty: Mapped[float] = mapped_column(DECIMAL(12, 2), server_default=text("0"))
    allocated_minutes: Mapped[float] = mapped_column(DECIMAL(10, 2), server_default=text("0"))
    started_at: Mapped[object | None] = mapped_column(DateTime, nullable=True)
    remark: Mapped[str | None] = mapped_column(String(500), nullable=True)
    created_at: Mapped[object] = mapped_column(DateTime)

    __table_args__ = (
        Index("idx_report_items_report", "report_id"),
        Index("idx_report_items_product", "project_no", "product_name"),
    )


class MiniAppReportAuditLog(Base):
    __tablename__ = "report_audit_logs"

    id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
    report_id: Mapped[int] = mapped_column(ForeignKey("production_reports.id"))
    reviewer_phone: Mapped[str] = mapped_column(ForeignKey("personnel.phone"))
    action: Mapped[str] = mapped_column(String(64))
    before_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
    after_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
    remark: Mapped[str | None] = mapped_column(String(500), nullable=True)
    created_at: Mapped[object] = mapped_column(DateTime)

    __table_args__ = (
        Index("idx_audit_report", "report_id"),
        Index("idx_audit_reviewer", "reviewer_phone", "created_at"),
    )


class MiniAppMoldLockFeedback(Base):
    __tablename__ = "mold_lock_feedbacks"

    id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
    attendance_point_name: Mapped[str] = mapped_column(String(128), server_default=text("''"))
    mold_name: Mapped[str] = mapped_column(String(255))
    process_name: Mapped[str] = mapped_column(String(128), server_default=text("''"))
    session_device_id: Mapped[int] = mapped_column(ForeignKey("work_session_devices.id"))
    reporter_phone: Mapped[str] = mapped_column(ForeignKey("personnel.phone"))
    occupied_phone: Mapped[str] = mapped_column(ForeignKey("personnel.phone"))
    status: Mapped[str] = mapped_column(String(32), server_default=text("'pending'"))
    read_at: Mapped[object | None] = mapped_column(DateTime, nullable=True)
    handled_at: Mapped[object | None] = mapped_column(DateTime, nullable=True)
    handled_by: Mapped[str | None] = mapped_column(ForeignKey("personnel.phone"), nullable=True)
    created_at: Mapped[object] = mapped_column(DateTime)

    __table_args__ = (
        Index("idx_mold_lock_feedback_point_read", "attendance_point_name", "read_at", "created_at"),
        Index("idx_mold_lock_feedback_status", "status", "created_at"),
    )


class MiniAppDeviceQRCode(Base):
    __tablename__ = "device_qrcodes"

    attendance_point_name: Mapped[str] = mapped_column(String(128), primary_key=True, server_default=text("''"))
    device_no: Mapped[str] = mapped_column(String(255), primary_key=True)
    process_name: Mapped[str] = mapped_column(String(128), primary_key=True, server_default=text("''"))
    qr_scene: Mapped[str] = mapped_column(String(128))
    qr_url: Mapped[str | None] = mapped_column(String(500), nullable=True)
    created_by: Mapped[str] = mapped_column(ForeignKey("personnel.phone"))
    created_at: Mapped[object] = mapped_column(DateTime)


class MiniAppDeviceQRCodeBatchTask(Base):
    __tablename__ = "device_qrcode_batch_tasks"

    id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
    file_name: Mapped[str] = mapped_column(String(255))
    status: Mapped[str] = mapped_column(String(32), server_default=text("'pending'"))
    item_count: Mapped[int] = mapped_column(Integer, server_default=text("0"))
    completed_count: Mapped[int] = mapped_column(Integer, server_default=text("0"))
    failed_count: Mapped[int] = mapped_column(Integer, server_default=text("0"))
    items_json: Mapped[list] = mapped_column(JSON)
    zip_url: Mapped[str | None] = mapped_column(String(500), nullable=True)
    error_message: Mapped[str | None] = mapped_column(String(1000), nullable=True)
    created_by: Mapped[str] = mapped_column(ForeignKey("personnel.phone"))
    started_at: Mapped[object | None] = mapped_column(DateTime, nullable=True)
    finished_at: Mapped[object | None] = mapped_column(DateTime, nullable=True)
    created_at: Mapped[object] = mapped_column(DateTime)
    updated_at: Mapped[object] = mapped_column(DateTime)

    __table_args__ = (
        Index("idx_device_qrcode_batch_tasks_creator", "created_by", "created_at"),
        Index("idx_device_qrcode_batch_tasks_status", "status", "created_at"),
    )


class MiniAppNotice(Base):
    __tablename__ = "notices"

    id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
    title: Mapped[str] = mapped_column(String(120))
    content: Mapped[str] = mapped_column(Text)
    sort_order: Mapped[int] = mapped_column(Integer, server_default=text("0"))
    is_active: Mapped[bool] = mapped_column(Boolean, server_default=text("1"))
    created_by: Mapped[str] = mapped_column(ForeignKey("personnel.phone"))
    created_at: Mapped[object] = mapped_column(DateTime)
    updated_at: Mapped[object] = mapped_column(DateTime)


class MiniAppNoticePoint(Base):
    __tablename__ = "notice_points"

    notice_id: Mapped[int] = mapped_column(ForeignKey("notices.id"), primary_key=True)
    attendance_point_name: Mapped[str] = mapped_column(ForeignKey("attendance_points.name"), primary_key=True)
    created_at: Mapped[object] = mapped_column(DateTime)


class MiniAppReconciliationLedgerEntry(Base):
    __tablename__ = "reconciliation_ledger_entries"

    attendance_point_name: Mapped[str] = mapped_column(String(128), primary_key=True, server_default=text("''"))
    year: Mapped[int] = mapped_column(Integer, primary_key=True)
    month: Mapped[int] = mapped_column(Integer, primary_key=True)
    product_name: Mapped[str] = mapped_column(String(255), primary_key=True)
    reconciled_good_qty: Mapped[float] = mapped_column(DECIMAL(14, 2), server_default=text("0"))
    return_qty: Mapped[float] = mapped_column(DECIMAL(14, 2), server_default=text("0"))
    updated_by: Mapped[str | None] = mapped_column(String(20), nullable=True)
    created_at: Mapped[object] = mapped_column(DateTime)
    updated_at: Mapped[object] = mapped_column(DateTime)

    __table_args__ = (
        Index("idx_reconciliation_product", "product_name"),
        Index("idx_reconciliation_updated", "updated_at"),
    )
