using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;

namespace ExperionCrawler.Core.Domain.Entities;

/// <summary>OPC UA 노드 태그 읽기 결과 (메모리)</summary>
public class ExperionTag
{
    public int    Id          { get; set; }
    public string NodeId      { get; set; } = string.Empty;
    public string TagName     { get; set; } = string.Empty;
    public string DisplayName { get; set; } = string.Empty;
    public string? Value      { get; set; }
    public string? DataType   { get; set; }
    public string StatusCode  { get; set; } = "Good";
    public DateTime Timestamp { get; set; } = DateTime.UtcNow;
    public bool IsGood => StatusCode == "Good";
}

/// <summary>크롤링으로 수집한 레코드 (DB/CSV 저장 단위)</summary>
public class ExperionRecord
{
    public int    Id          { get; set; }
    public string NodeId      { get; set; } = string.Empty;
    public string? Value      { get; set; }
    public string StatusCode  { get; set; } = "Good";
    public DateTime CollectedAt { get; set; } = DateTime.UtcNow;
    public string? SessionId  { get; set; }
}

/// <summary>Experion 서버 접속 설정</summary>
public class ExperionServerConfig
{
    public int    Id               { get; set; }
    public string ServerHostName   { get; set; } = string.Empty;
    public int    Port             { get; set; } = 4840;
    public string ClientHostName   { get; set; } = string.Empty;
    public string UserName         { get; set; } = string.Empty;
    public string Password         { get; set; } = string.Empty;

    public string EndpointUrl    => $"opc.tcp://{ServerHostName}:{Port}";
    public string ApplicationUri => $"urn:{ClientHostName}:ExperionCrawlerClient";
}

/// <summary>OPC UA 전체 노드맵 원시 데이터 (AssetLoader binary COPY 대상)</summary>
[Table("raw_node_map")]
public class RawNodeMap
{
    [Column("id")]       public int    Id       { get; set; }
    [Column("level")]    public int    Level    { get; set; }
    [Column("class")]    public string Class    { get; set; } = string.Empty;
    [Column("name")]     public string Name     { get; set; } = string.Empty;
    [Column("node_id")]  public string NodeId   { get; set; } = string.Empty;
    [Column("data_type")]public string DataType { get; set; } = string.Empty;
}

/// <summary>raw_node_map 에서 빌드된 master 테이블</summary>
[Table("node_map_master")]
public class NodeMapMaster
{
    [Column("id")]       public int    Id       { get; set; }
    [Column("level")]    public int    Level    { get; set; }
    [Column("class")]    public string Class    { get; set; } = string.Empty;
    [Column("name")]     public string Name     { get; set; } = string.Empty;
    [Column("node_id")]  public string NodeId   { get; set; } = string.Empty;
    [Column("data_type")]public string DataType { get; set; } = string.Empty;
}

/// <summary>realtime_table — 실시간 모니터링 포인트</summary>
[Table("realtime_table")]
public class RealtimePoint
{
    [Column("id")]        public int     Id        { get; set; }
    [Column("tagname")]   public string  TagName   { get; set; } = string.Empty;
    [Column("node_id")]   public string  NodeId    { get; set; } = string.Empty;
    [Column("livevalue")] public string? LiveValue { get; set; }
    [Column("timestamp")] public DateTime Timestamp { get; set; } = DateTime.UtcNow;
}

/// <summary>history_table — 시계열 이력 스냅샷</summary>
[Table("history_table")]
public class HistoryRecord
{
    [Column("id")]          public int     Id          { get; set; }
    [Column("tagname")]     public string  TagName     { get; set; } = string.Empty;
    [Column("node_id")]     public string  NodeId      { get; set; } = string.Empty;
    [Column("value")]       public string? Value       { get; set; }
    [Column("recorded_at")] public DateTime RecordedAt { get; set; } = DateTime.UtcNow;
}

/// <summary>statuscode.json 항목</summary>
public class ExperionStatusCodeInfo
{
    public string Name        { get; set; } = string.Empty;
    public string Hex         { get; set; } = string.Empty;
    public ulong  Decimal     { get; set; }
    public string Description { get; set; } = string.Empty;
}

/// <summary>P&ID 그래프 생성 작업 상태 (DB 저장용)</summary>
[Table("pid_graph_status")]
public class PidGraphStatus
{
    [Column("task_id")]    public string TaskId { get; set; } = string.Empty;
    [Column("progress")]   public double Progress { get; set; }
    [Column("status")]     public string Status { get; set; } = "Pending";
    [Column("message")]    public string Message { get; set; } = string.Empty;
    [Column("updated_at")] public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
}

/// <summary>fastSession — 데이터 수집 세션 메타</summary>
[Table("fast_session")]
public class FastSession
{
    [Column("id")]             public int       Id            { get; set; }
    [Column("name")]           public string    Name          { get; set; } = string.Empty;
    [Column("started_at")]     public DateTime  StartedAt     { get; set; }
    [Column("ended_at")]       public DateTime? EndedAt       { get; set; }
    [Column("status")]         public string    Status        { get; set; } = "Pending";
    // Status 허용값: Pending / Running / Completed / Cancelled / Failed / RowLimitReached
    [Column("sampling_ms")]    public int       SamplingMs    { get; set; }
    [Column("duration_sec")]   public int       DurationSec   { get; set; }
    [Column("tag_list")]       public string    TagList       { get; set; } = "[]"; // JSONB → string[] 직렬화
    [Column("row_count")]      public int       RowCount      { get; set; }
    [Column("retention_days")] public int?      RetentionDays { get; set; } // null = 무한 보관
    [Column("pinned")]         public bool      Pinned        { get; set; }
}

/// <summary>fastRecord — 시계열 데이터 (Long 포맷: 태그 1행/시점)</summary>
[Table("fast_record")]
public class FastRecord
{
    [NotMapped]             public int      Id         { get; set; }
    [Column("session_id")]  public int      SessionId  { get; set; }
    [Column("recorded_at")] public DateTime RecordedAt { get; set; }
    [Column("tagname")]     public string   TagName    { get; set; } = string.Empty;
    [Column("value")]       public string?  Value      { get; set; }
}

/// <summary>tag_metadata — 태그 메타데이터 (변경 드묾)</summary>
[Table("tag_metadata")]
public class TagMetadata
{
    [Column("id")]          public int       Id          { get; set; }
    [Column("base_tag")]    public string    BaseTag     { get; set; } = string.Empty;
    [Column("attribute")]   public string    Attribute   { get; set; } = string.Empty;
    [Column("value")]       public string?   Value       { get; set; }
    [Column("node_id")]     public string?   NodeId      { get; set; }
    [Column("loaded_at")]   public DateTime  LoadedAt    { get; set; } = DateTime.UtcNow;
}

// ── Knowledge Base (RAG) ─────────────────────────────────────────────────────

/// <summary>kb_collections — 컬렉션 레지스트리(seed: system_instrument 등 5종)</summary>
[Table("kb_collections")]
public class KbCollection
{
    [Key]
    [Column("collection_key")] public string CollectionKey   { get; set; } = string.Empty;
    [Column("display_name")]   public string DisplayName     { get; set; } = string.Empty;
    [Column("qdrant_name")]    public string QdrantName      { get; set; } = string.Empty;
    [Column("chunking_policy", TypeName = "jsonb")]
                               public string ChunkingPolicy  { get; set; } = "{}";
    [Column("description")]    public string? Description    { get; set; }
    [Column("is_active")]      public bool   IsActive        { get; set; } = true;
    [Column("created_at")]     public DateTime CreatedAt     { get; set; } = DateTime.UtcNow;
}

/// <summary>kb_documents — 업로드된 원본 문서 메타</summary>
[Table("kb_documents")]
public class KbDocument
{
    [Key]
    [Column("id")]              public Guid     Id             { get; set; } = Guid.NewGuid();
    [Column("collection_key")]  public string   CollectionKey  { get; set; } = string.Empty;
    [Column("title")]           public string   Title          { get; set; } = string.Empty;
    [Column("original_path")]   public string   OriginalPath   { get; set; } = string.Empty;
    [Column("file_sha256")]     public string   FileSha256     { get; set; } = string.Empty;
    [Column("file_size")]       public long?    FileSize       { get; set; }
    [Column("mime_type")]       public string?  MimeType       { get; set; }
    [Column("tags")]            public string[] Tags           { get; set; } = Array.Empty<string>();
    [Column("status")]          public string   Status         { get; set; } = "pending";
    // pending / parsing / embedding / indexed / failed / disabled
    [Column("chunk_count")]     public int      ChunkCount     { get; set; }
    [Column("error_message")]   public string?  ErrorMessage   { get; set; }
    [Column("uploaded_by")]     public string?  UploadedBy     { get; set; }
    [Column("uploaded_at")]     public DateTime UploadedAt     { get; set; } = DateTime.UtcNow;
    [Column("indexed_at")]      public DateTime? IndexedAt     { get; set; }
    [Column("disabled_at")]     public DateTime? DisabledAt    { get; set; }
}

/// <summary>kb_ingest_jobs — 비동기 처리 큐</summary>
[Table("kb_ingest_jobs")]
public class KbIngestJob
{
    [Key]
    [Column("id")]           public long      Id          { get; set; }
    [Column("doc_id")]       public Guid      DocId       { get; set; }
    [Column("stage")]        public string    Stage       { get; set; } = "parse"; // parse / embed / index
    [Column("attempts")]     public int       Attempts    { get; set; }
    [Column("last_error")]   public string?   LastError   { get; set; }
    [Column("enqueued_at")]  public DateTime  EnqueuedAt  { get; set; } = DateTime.UtcNow;
    [Column("started_at")]   public DateTime? StartedAt   { get; set; }
    [Column("finished_at")]  public DateTime? FinishedAt  { get; set; }
}

/// <summary>kb_admin_credential — 관리자 비밀번호(단일 행)</summary>
[Table("kb_admin_credential")]
public class KbAdminCredential
{
    [Key]
    [Column("id")]            public int      Id            { get; set; } = 1;
    [Column("password_hash")] public string   PasswordHash  { get; set; } = string.Empty;
    [Column("salt")]          public string   Salt          { get; set; } = string.Empty;
    [Column("algorithm")]     public string   Algorithm     { get; set; } = "argon2id";
    [Column("updated_at")]    public DateTime UpdatedAt     { get; set; } = DateTime.UtcNow;
}

/// <summary>kb_admin_sessions — 관리자 세션 토큰</summary>
[Table("kb_admin_sessions")]
public class KbAdminSession
{
    [Key]
    [Column("token")]      public string   Token      { get; set; } = string.Empty;
    [Column("issued_at")]  public DateTime IssuedAt   { get; set; } = DateTime.UtcNow;
    [Column("expires_at")] public DateTime ExpiresAt  { get; set; }
    [Column("client_ip")]  public string?  ClientIp   { get; set; }
}

/// <summary>event_history_table — 디지털 포인트 상태 변경 이벤트</summary>
[Table("event_history_table")]
public class EventHistoryRecord
{
    [Key]
    [Column("id")]              public long      Id              { get; set; }
    [Column("tagname")]         public string    TagName         { get; set; } = string.Empty;
    [Column("node_id")]         public string    NodeId          { get; set; } = string.Empty;
    [Column("prev_value")]      public string?   PrevValue       { get; set; }
    [Column("curr_value")]      public string    CurrValue       { get; set; } = string.Empty;
    [Column("event_type")]      public string    EventType       { get; set; } = string.Empty;
    [Column("event_time")]      public DateTime  EventTime       { get; set; } = DateTime.UtcNow;
    [Column("area")]            public string?   Area            { get; set; }
    [Column("sub_area")]        public string?   SubArea         { get; set; }
    [Column("duration_seconds")] public int?     DurationSeconds { get; set; }
    [Column("metadata")]        public string?   Metadata        { get; set; }
    [Column("created_at")]      public DateTime  CreatedAt       { get; set; } = DateTime.UtcNow;
}
