import { Component } from '@angular/core';
import { CodeBlockComponent } from '../components/code-block.component';

@Component({
  selector: 'app-queries-sequences-page',
  standalone: true,
  imports: [CodeBlockComponent],
  templateUrl: './queries-sequences.page.html',
})
export class QueriesSequencesPage {
  basicSequence = `use prax::sequence::{Sequence, SequenceBuilder};

// Create a sequence
let order_seq = Sequence::builder()
    .name("order_number_seq")
    .start(1000)
    .increment(1)
    .min_value(1)
    .max_value(9_999_999)
    .cycle(false)
    .cache(20)  // Pre-allocate 20 values for performance
    .build();

// Generate SQL
let sql = order_seq.to_postgres_sql();
// CREATE SEQUENCE order_number_seq
//   START WITH 1000
//   INCREMENT BY 1
//   MINVALUE 1
//   MAXVALUE 9999999
//   NO CYCLE
//   CACHE 20;`;

  sequenceOps = `use prax::sequence::ops;

// Get next value (PostgreSQL/MSSQL)
let next = ops::nextval("order_number_seq").exec(&client).await?;
// PostgreSQL: SELECT nextval('order_number_seq')
// MSSQL: SELECT NEXT VALUE FOR order_number_seq

// Get current value (within session)
let current = ops::currval("order_number_seq").exec(&client).await?;
// PostgreSQL: SELECT currval('order_number_seq')
// MSSQL: SELECT current_value FROM sys.sequences WHERE name = 'order_number_seq'

// Set sequence value
ops::setval("order_number_seq", 5000, true).exec(&client).await?;
// PostgreSQL: SELECT setval('order_number_seq', 5000, true)
// MSSQL: ALTER SEQUENCE order_number_seq RESTART WITH 5000

// Use in INSERT with DEFAULT
let sql = format!(
    "INSERT INTO orders (order_number, total) VALUES ({}, $1)",
    ops::default_nextval("order_number_seq")
);`;

  autoIncrement = `use prax::sequence::auto_increment;

// Get the column definition for auto-increment
let column = auto_increment::column_definition(DatabaseType::PostgreSQL);
// PostgreSQL: SERIAL / BIGSERIAL or GENERATED ALWAYS AS IDENTITY
// MySQL: AUTO_INCREMENT
// SQLite: INTEGER PRIMARY KEY AUTOINCREMENT
// MSSQL: IDENTITY(1,1)

// Get last inserted ID
let id = auto_increment::last_insert_id(&client).await?;
// PostgreSQL: Uses RETURNING
// MySQL: SELECT LAST_INSERT_ID()
// SQLite: SELECT last_insert_rowid()
// MSSQL: SELECT SCOPE_IDENTITY()

// Set auto-increment starting value
auto_increment::set_start_value(&client, "users", 1000).await?;
// PostgreSQL: ALTER SEQUENCE users_id_seq RESTART WITH 1000
// MySQL: ALTER TABLE users AUTO_INCREMENT = 1000
// MSSQL: DBCC CHECKIDENT ('users', RESEED, 999)`;

  mongoCounter = `use prax::sequence::mongodb::{CounterBuilder, counter};

// MongoDB counter pattern using findAndModify
let counter = CounterBuilder::new("order_numbers")
    .initial_value(1000)
    .increment(1)
    .build();

// Get next value atomically
let next = counter.next(&client).await?;
// db.counters.findAndModify({
//   query: { _id: "order_numbers" },
//   update: { $inc: { seq: 1 } },
//   upsert: true,
//   new: true
// })

// Batch allocation (get N values at once)
let batch = counter.next_batch(&client, 100).await?;
// Returns range: start..end (e.g., 1000..1100)

// Use in your model
let order = Order {
    order_number: counter::next("order_numbers", &client).await?,
    items: vec![...],
    total: 99.99,
};`;

  sequencePatterns = `use prax::sequence::patterns;

// Order number with prefix: ORD-2024-00001
let order_number = patterns::prefixed_sequence("orders", "ORD")
    .with_year()
    .zero_pad(5)
    .build();

let num = order_number.next(&client).await?;
// Returns: "ORD-2024-00001", "ORD-2024-00002", etc.

// Invoice number resets yearly
let invoice = patterns::yearly_reset_sequence("invoices")
    .format("INV-{year}-{seq:06}")
    .build();

// Round-robin assignment (for load balancing)
let worker = patterns::round_robin("workers", 4);
let assigned = worker.next(&client).await?;  // 0, 1, 2, 3, 0, 1, ...

// Countdown sequence (for limited inventory)
let tickets = patterns::countdown("event_tickets", 1000);
let ticket_num = tickets.next(&client).await?;  // 1000, 999, 998...
if ticket_num == 0 {
    return Err(Error::SoldOut);
}`;

  identityColumns = `// PostgreSQL GENERATED AS IDENTITY (preferred over SERIAL)
model User {
  id Int @id @default(auto()) @db.Identity
  // GENERATED ALWAYS AS IDENTITY
}

// GENERATED BY DEFAULT allows manual inserts
model ImportedUser {
  id Int @id @default(auto()) @db.Identity("BY DEFAULT")
  // GENERATED BY DEFAULT AS IDENTITY
}

// MSSQL IDENTITY
model Order {
  id Int @id @default(auto())
  // IDENTITY(1,1)
}

// Custom identity options
model CustomId {
  id Int @id @default(auto()) @db.Identity(start: 1000, increment: 10)
  // IDENTITY(1000, 10)
}`;

  sequenceMigration = `use prax_migrate::{Migration, MigrationStep};

// Migration for sequence changes
let migration = Migration::new("add_order_sequence")
    .up(r#"
        CREATE SEQUENCE order_number_seq
            START WITH 1000
            INCREMENT BY 1
            NO CYCLE
            CACHE 20;

        ALTER TABLE orders
            ALTER COLUMN order_number SET DEFAULT nextval('order_number_seq');
    "#)
    .down(r#"
        ALTER TABLE orders ALTER COLUMN order_number DROP DEFAULT;
        DROP SEQUENCE order_number_seq;
    "#);

// For MSSQL
let mssql_migration = Migration::new("add_order_sequence")
    .up(r#"
        CREATE SEQUENCE dbo.order_number_seq
            START WITH 1000
            INCREMENT BY 1
            NO CYCLE
            CACHE 20;

        ALTER TABLE orders
            ADD CONSTRAINT DF_orders_number
            DEFAULT NEXT VALUE FOR dbo.order_number_seq FOR order_number;
    "#);`;
}
