"""Issuer Database Tables/Models.

Models of the Traction tables for Issuer and related data.

"""
import uuid
from datetime import datetime
from typing import List, Optional

from sqlalchemy.orm import selectinload
from sqlmodel import Field, Relationship
from sqlalchemy import (
    Column,
    func,
    String,
    select,
    desc,
    JSON,
    text,
)
from sqlalchemy.dialects.postgresql import UUID, TIMESTAMP, ARRAY
from sqlmodel.ext.asyncio.session import AsyncSession

from api.db.models.base import BaseModel
from api.db.models.v1.contact import Contact
from api.db.models.v1.governance import CredentialTemplate

from api.endpoints.models.v1.errors import (
    NotFoundError,
)


class IssuerCredential(BaseModel, table=True):
    """Issuer Credential.

    Model for the Issuer Credential table (postgresql specific dialects in use).
    This will track Issuer Credentials for the Tenants.

    Attributes:
      issuer_credential_id: Traction ID for issuer credential
      credential_template_id: Traction Credential Template ID
      contact_id: Traction Contact ID
      cred_def_id: Credential Definition ID (ledger)
      tenant_id: Traction Tenant ID
      status: Business and Tenant indicator for Credential state; independent of AcaPy
        Credential Exchange state
      external_reference_id: Set by tenant to correlate this Credential with entity in
        external system
      revoked: when True, this credential has been revoked
      deleted: Issuer Credential "soft" delete indicator.
      preview_persisted: when True, store the credential attributes and preview
      tags: Set by tenant for arbitrary grouping of Credentials
      comment: Comment supplied when issuing
      credential_preview: attributes (list of name / values ) for offered/issued cred.
        This will be empty once offer is made and preview_persisted = False.
      revocation_comment: comment entered when revoking Credential
      state: The underlying AcaPy credential exchange state
      thread_id: AcaPy thread id
      credential_exchange_id: AcaPy id for the credential exchange
      revoc_reg_id: revocation registry id (needed for revocation)
      revocation_id: credential revocation id (needed for revocation)
      created_at: Timestamp when record was created in Traction
      updated_at: Timestamp when record was last modified in Traction
    """

    __tablename__ = "issuer_credential"

    issuer_credential_id: uuid.UUID = Field(
        sa_column=Column(
            UUID(as_uuid=True),
            primary_key=True,
            server_default=text("gen_random_uuid()"),
        )
    )
    credential_template_id: uuid.UUID = Field(
        foreign_key="credential_template.credential_template_id", index=True
    )
    tenant_id: uuid.UUID = Field(foreign_key="tenant.id", index=True)
    contact_id: uuid.UUID = Field(foreign_key="contact.contact_id", index=True)
    status: str = Field(nullable=False)
    external_reference_id: str = Field(nullable=True)
    revoked: bool = Field(nullable=False, default=False)
    deleted: bool = Field(nullable=False, default=False)
    tags: List[str] = Field(sa_column=Column(ARRAY(String)))
    preview_persisted: bool = 