"""Create table change type and SQL generation.

PostgreSQL 17 CREATE TABLE Synopsis:
https://www.postgresql.org/docs/17/sql-createtable.html

CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name ( [
  { column_name data_type [ STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN | DEFAULT } ] [ COMPRESSION compression_method ] [ COLLATE collation ] [ column_constraint [ ... ] ]
    | table_constraint
    | LIKE source_table [ like_option ... ] }
    [, ... ]
] )
[ INHERITS ( parent_table [, ... ] ) ]
[ PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ]
[ USING method ]
[ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
[ TABLESPACE tablespace_name ]

Currently supported:
- Basic table creation with columns
- Column data types with precision/scale
- NOT NULL constraints
- DEFAULT expressions
- INHERITS clause
- WITH storage parameters
- Row Level Security (RLS) settings

Not yet supported:
- Column STORAGE settings (PLAIN, EXTERNAL, EXTENDED, MAIN)
- Column COMPRESSION settings
- Column COLLATE settings
- Column constraints (CHECK, UNIQUE, PRIMARY KEY, REFERENCES)
- Table constraints (CHECK, UNIQUE, PRIMARY KEY, FOREIGN KEY, EXCLUDE)
- LIKE clause for copying table structure
- PARTITION BY clause (RANGE, LIST, HASH partitioning)
- USING method for access method
- ON COMMIT behavior for temporary tables
- TABLESPACE clause
- Generated columns (GENERATED ALWAYS AS)
- Identity columns (GENERATED BY DEFAULT AS IDENTITY)
- UNLOGGED tables (storage detail that changes automatically)

Intentionally not supported (not needed for DDL generation):
- TEMPORARY/TEMP tables (not persistent schema objects)
- IF NOT EXISTS (pgdelta tracks existence, so always knows if table exists)
- WITHOUT OIDS (deprecated PostgreSQL feature)
- GLOBAL/LOCAL modifiers for temporary tables
"""

from dataclasses import dataclass
from typing import Any

from ...model import PgAttribute


@dataclass(frozen=True)
class CreateTable:
    """Create table change."""

    stable_id: str
    namespace: str
    relname: str
    columns: list[PgAttribute]
    table_options: dict[str, Any] | None = None
    inherits_from: list[str] | None = None


def generate_create_table_sql(change: CreateTable) -> str:
    """Generate CREATE TABLE SQL."""
    quoted_schema = f'"{change.namespace}"'
    quoted_table = f'"{change.relname}"'

    # Start with CREATE TABLE
    sql_parts = [f"CREATE TABLE {quoted_schema}.{quoted_table} ("]

    # Add columns
    column_defs = []
    for col in change.columns:
        col_def = f'  "{col.attname}" {col.formatted_type}'

        # Handle generated columns
        if col.is_generated:
            col_def += f" GENERATED ALWAYS AS ({col.generated_expression}) STORED"
            # Add NOT NULL constraint after STORED for generated columns
            if col.attnotnull:
                col_def += " NOT NULL"
        else:
            # For regular columns, add DEFAULT then NOT NULL
            if col.default_value:
                col_def += f" DEFAULT {col.default_value}"
            if col.attnotnull:
                col_def += " NOT NULL"

        column_defs.append(col_def)

    sql_parts.append("\n" + ",\n".join(column_defs) + "\n")
    sql_parts.append(")")

    # Add inheritance
    if change.inherits_from:
        inherits_tables = [f'"{table}"' for table in change.inherits_from]
        sql_parts.append(f" INHERITS ({', '.join(inherits_tables)})")

    # Add table options
    if change.table_options:
        options = []
        for key, value in change.table_options.items():
            if isinstance(value, bool):
                options.append(f"{key}={str(value).lower()}")
            else:
                options.append(f"{key}={value}")
        if options:
            sql_parts.append(f" WITH ({', '.join(options)})")

    sql_statements = ["".join(sql_parts) + ";"]

    # Add sequence ownership statements for columns with sequence defaults
    for column in change.columns:
        if column.default_value and "nextval(" in column.default_value:
            # Extract sequence name from default like "nextval('schema.seq_name'::regclass)"
            import re

            match = re.search(r"nextval\('([^']+)'", column.default_value)
            if match:
                sequence_name = match.group(1)
                # Handle quoted identifiers
                if '"' in sequence_name:
                    # Already quoted
                    quoted_seq = sequence_name
                else:
                    # Need to quote the parts
                    parts = sequence_name.split(".")
                    quoted_seq = ".".join(f'"{part}"' for part in parts)

                ownership_sql = (
                    f"ALTER SEQUENCE {quoted_seq} "
                    f'OWNED BY "{change.namespace}"."{change.relname}"."{column.attname}";'
                )
                sql_statements.append(ownership_sql)

    return "\n".join(sql_statements)
