<?php
/**
 * File Path: includes/export/class-mbs-book-bible-cell-helpers.php
 *
 * Book Bible Cell Helpers Trait
 *
 * Low-level cell-writing utilities shared by MBS_Book_Bible_Tab_Writer and
 * its subclasses. All methods are pure functions of their arguments -- no
 * instance state, no side effects beyond calling MBS_Book_Bible_Builder.
 *
 * @package MyBookShowroom
 * @since   2.6.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

trait MBS_Book_Bible_Cell_Helpers { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedTraitFound -- mbs_/MBS_ prefix is correct; scanner not configured with plugin prefix

	// -------------------------------------------------------------------------
	// Structural helpers
	// -------------------------------------------------------------------------

	/**
	 * Write colophon rows 0-2 (title block, attribution, spacer) to a sheet.
	 *
	 * @param MBS_Book_Bible_Builder $b    Builder instance.
	 * @param int                    $s    Sheet index.
	 * @param array                  $data Gathered book data.
	 * @return void
	 */
	protected function colophon( MBS_Book_Bible_Builder $b, int $s, array $data ): void {
		// Row 0: title block (left A-D) + both attribution lines (right E-H, wrapped).
		// Both attribution lines combined with LF so they stack in a single cell.
		// set_row_height(36) gives two comfortable lines of 10pt text.
		$right = 'Book Bible concept by Hallee Bridgeman | used by permission'
			. "\n" . 'My Book Showroom WordPress Plugin | ' . site_url();
		$this->fill( $b, $s, 0, 0, 3, $data['title'] . ' -- Book Bible', 6 );
		$this->fill( $b, $s, 0, 4, 7, $right, 1, true );  // style 1+wrap
		$b->set_row_height( $s, 0, 36.0 );
		// Rows 1-2: spacers
		$this->fill( $b, $s, 1, 0, 7, '', 0 );
		$this->fill( $b, $s, 2, 0, 7, '', 0 );
	}

	/**
	 * Section header row: navy fill, white bold text, cols 0-7 merged.
	 *
	 * @param MBS_Book_Bible_Builder $b     Builder instance.
	 * @param int                    $s     Sheet index.
	 * @param int                    $row   0-based row number.
	 * @param string                 $label Header label text.
	 * @return void
	 */
	protected function hdr( MBS_Book_Bible_Builder $b, int $s, int $row, string $label ): void {
		$this->fill( $b, $s, $row, 0, 7, $label, 2 );
	}

	/**
	 * Empty spacer row spanning cols 0-7, style 0.
	 *
	 * @param MBS_Book_Bible_Builder $b   Builder instance.
	 * @param int                    $s   Sheet index.
	 * @param int                    $row 0-based row number.
	 * @return void
	 */
	protected function sp( MBS_Book_Bible_Builder $b, int $s, int $row ): void {
		$this->fill( $b, $s, $row, 0, 7, '', 0 );
	}

	// -------------------------------------------------------------------------
	// Cell fill helpers
	// -------------------------------------------------------------------------

	/**
	 * Single-row merged fill. Top-left carries value; remaining cells are empty with same style.
	 *
	 * @param MBS_Book_Bible_Builder $b     Builder instance.
	 * @param int                    $s     Sheet index.
	 * @param int                    $row   0-based row.
	 * @param int                    $c1    0-based start column.
	 * @param int                    $c2    0-based end column.
	 * @param string                 $value Cell value.
	 * @param int                    $style Style index 0-6.
	 * @param bool                   $wrap  Whether to wrap text.
	 * @return void
	 */
	protected function fill( MBS_Book_Bible_Builder $b, int $s, int $row, int $c1, int $c2, string $value, int $style, bool $wrap = false ): void {
		$range = ( $c1 < $c2 ) ? static::r( $row, $c1, $c2 ) : null;
		$b->set_cell( $s, $row, $c1, $value, $style, 's', $range, $wrap );
		for ( $c = $c1 + 1; $c <= $c2; $c++ ) {
			$b->set_cell( $s, $row, $c, '', $style );
		}
	}

	/**
	 * Single-row merged formula fill. Top-left carries formula; remaining cells are empty.
	 *
	 * @param MBS_Book_Bible_Builder $b       Builder instance.
	 * @param int                    $s       Sheet index.
	 * @param int                    $row     0-based row.
	 * @param int                    $c1      0-based start column.
	 * @param int                    $c2      0-based end column.
	 * @param string                 $formula Excel formula string (without leading '=').
	 * @param int                    $style   Style index 0-6.
	 * @param bool                   $wrap    Whether to wrap text.
	 * @return void
	 */
	protected function fill_formula( MBS_Book_Bible_Builder $b, int $s, int $row, int $c1, int $c2, string $formula, int $style, bool $wrap = false ): void {
		$range = ( $c1 < $c2 ) ? static::r( $row, $c1, $c2 ) : null;
		$b->set_formula( $s, $row, $c1, $formula, $style, $range, $wrap );
		for ( $c = $c1 + 1; $c <= $c2; $c++ ) {
			$b->set_cell( $s, $row, $c, '', $style );
		}
	}

	/**
	 * Multi-row merged fill. Top-left carries value; all other cells in range are empty.
	 *
	 * @param MBS_Book_Bible_Builder $b      Builder instance.
	 * @param int                    $s      Sheet index.
	 * @param int                    $r1     0-based start row.
	 * @param int                    $r2     0-based end row.
	 * @param int                    $c1     0-based start column.
	 * @param int                    $c2     0-based end column.
	 * @param string                 $value  Cell value.
	 * @param int                    $style  Style index 0-6.
	 * @param bool                   $wrap   Whether to wrap text.
	 * @return void
	 */
	protected function mrow( MBS_Book_Bible_Builder $b, int $s, int $r1, int $r2, int $c1, int $c2, string $value, int $style, bool $wrap = true ): void {
		$range = static::r( $r1, $c1, $c2, $r2 );
		$b->set_cell( $s, $r1, $c1, $value, $style, 's', $range, $wrap );
		for ( $r = $r1; $r <= $r2; $r++ ) {
			for ( $c = $c1; $c <= $c2; $c++ ) {
				if ( $r === $r1 && $c === $c1 ) {
					continue;
				}
				$b->set_cell( $s, $r, $c, '', $style );
			}
		}
	}

	/**
	 * Label/data row: col 0 = label (style 3); cols c1-c2 merged = data (auto style).
	 *
	 * @param MBS_Book_Bible_Builder $b        Builder instance.
	 * @param int                    $s        Sheet index.
	 * @param int                    $row      0-based row.
	 * @param string                 $label    Label text.
	 * @param string                 $value    Data value.
	 * @param int                    $c1       0-based data start column (default 1).
	 * @param int                    $c2       0-based data end column (default 7).
	 * @param bool                   $expected Use amber (style 5) when value is empty.
	 * @param bool                   $wrap     Whether to wrap text in data cell.
	 * @return void
	 */
	protected function lbl( MBS_Book_Bible_Builder $b, int $s, int $row, string $label, string $value, int $c1 = 1, int $c2 = 7, bool $expected = false, bool $wrap = false ): void {
		$b->set_cell( $s, $row, 0, $label, 3 );
		$ds    = ( $expected && '' === $value ) ? 5 : 4;
		$range = ( $c1 < $c2 ) ? static::r( $row, $c1, $c2 ) : null;
		$b->set_cell( $s, $row, $c1, $value, $ds, 's', $range, $wrap );
		for ( $c = $c1 + 1; $c <= $c2; $c++ ) {
			$b->set_cell( $s, $row, $c, '', $ds );
		}
	}

	/**
	 * Two-column row using expected-flag auto-amber for data styles.
	 *
	 * Left:  col 0 label (style 3), cols 1-3 merged data.
	 * Right: col 4 label (style 3), cols 5-7 merged data.
	 *
	 * @param MBS_Book_Bible_Builder $b    Builder instance.
	 * @param int                    $s    Sheet index.
	 * @param int                    $row  0-based row.
	 * @param string                 $lbl1 Left label.
	 * @param string                 $val1 Left value.
	 * @param bool                   $exp1 Amber if left value empty.
	 * @param string                 $lbl2 Right label.
	 * @param string                 $val2 Right value.
	 * @param bool                   $exp2 Amber if right value empty.
	 * @return void
	 */
	protected function two( MBS_Book_Bible_Builder $b, int $s, int $row, string $lbl1, string $val1, bool $exp1, string $lbl2, string $val2, bool $exp2 ): void {
		$this->two_ds( $b, $s, $row,
			$lbl1, $val1, ( $exp1 && '' === $val1 ) ? 5 : 4,
			$lbl2, $val2, ( $exp2 && '' === $val2 ) ? 5 : 4
		);
	}

	/**
	 * Two-column row with explicit data styles (no auto amber logic).
	 *
	 * Left:  col 0 label (style 3), cols 1-3 merged data (style $ds1).
	 * Right: col 4 label (style 3), cols 5-7 merged data (style $ds2).
	 *
	 * @param MBS_Book_Bible_Builder $b    Builder instance.
	 * @param int                    $s    Sheet index.
	 * @param int                    $row  0-based row.
	 * @param string                 $lbl1 Left label.
	 * @param string                 $val1 Left value.
	 * @param int                    $ds1  Left data style index.
	 * @param string                 $lbl2 Right label.
	 * @param string                 $val2 Right value.
	 * @param int                    $ds2  Right data style index.
	 * @return void
	 */
	protected function two_ds( MBS_Book_Bible_Builder $b, int $s, int $row, string $lbl1, string $val1, int $ds1, string $lbl2, string $val2, int $ds2 ): void {
		$b->set_cell( $s, $row, 0, $lbl1, 3 );
		$b->set_cell( $s, $row, 1, $val1, $ds1, 's', static::r( $row, 1, 3 ) );
		$b->set_cell( $s, $row, 2, '',    $ds1 );
		$b->set_cell( $s, $row, 3, '',    $ds1 );
		$b->set_cell( $s, $row, 4, $lbl2, 3 );
		$b->set_cell( $s, $row, 5, $val2, $ds2, 's', static::r( $row, 5, 7 ) );
		$b->set_cell( $s, $row, 6, '',    $ds2 );
		$b->set_cell( $s, $row, 7, '',    $ds2 );
	}

	/**
	 * Generate A1-notation range string from 0-based coordinates.
	 *
	 * @param int      $row  0-based start row.
	 * @param int      $c1   0-based start column.
	 * @param int      $c2   0-based end column.
	 * @param int|null $row2 0-based end row (null = same row as $row).
	 * @return string  A1-notation range, e.g. "B3:D5".
	 */
	protected static function r( int $row, int $c1, int $c2, ?int $row2 = null ): string {
		$cl = static function ( int $c ): string {
			if ( $c < 26 ) {
				return chr( 65 + $c );
			}
			return chr( 64 + (int) floor( $c / 26 ) ) . chr( 65 + ( $c % 26 ) );
		};
		return $cl( $c1 ) . ( $row + 1 ) . ':' . $cl( $c2 ) . ( ( $row2 ?? $row ) + 1 );
	}
}
