<?php
/**
 * ANCP Core - Sources Table (GEDCOM SOUR, spec-00 5.3).
 *
 * @package    AncestorPress\Core
 * @subpackage AncestorPress\Core\DB
 * @since      0.7.0
 */

namespace AncestorPress\Core;

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

class Sources_Table {

	public static function table() {
		return Tables::sources();
	}

	/**
	 * Fetch a source by tree + sourceID.
	 *
	 * @param  string $gedcom   Tree identifier.
	 * @param  string $sourceID Source reference (e.g. S1).
	 * @return object|null
	 */
	public static function get_by_ref( $gedcom, $sourceID ) {
		global $wpdb;
		return $wpdb->get_row( $wpdb->prepare( 'SELECT * FROM %i WHERE gedcom = %s AND sourceID = %s LIMIT 1', self::table(), $gedcom, $sourceID ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
	}

	/**
	 * All sources for a tree, ordered by title.
	 *
	 * @param  string $gedcom Tree identifier.
	 * @return array
	 */
	public static function get_by_tree( $gedcom ) {
		global $wpdb;
		return $wpdb->get_results( $wpdb->prepare( 'SELECT * FROM %i WHERE gedcom = %s ORDER BY title ASC, sourceID ASC', self::table(), $gedcom ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
	}

	/**
	 * Count sources in a tree.
	 *
	 * @param  string $gedcom Tree identifier.
	 * @return int
	 */
	public static function count_by_tree( $gedcom ) {
		global $wpdb;
		return (int) $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(*) FROM %i WHERE gedcom = %s', self::table(), $gedcom ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
	}

	/**
	 * Insert a source record.
	 *
	 * @param  array $data Field => value pairs.
	 * @return int|false   New row ID or false.
	 */
	public static function insert( $data ) {
		global $wpdb;
		$now  = Tables::now();
		$data = array_merge(
			array(
				'created_by_user_id' => get_current_user_id(),
				'created_at'         => $now,
				'updated_at'         => $now,
			),
			$data
		);
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- core table write.
		$result = $wpdb->insert( self::table(), $data );
		return $result ? (int) $wpdb->insert_id : false;
	}

	/**
	 * Update a source by row ID.
	 *
	 * @param  int   $id   Row ID.
	 * @param  array $data Field => value pairs.
	 * @return int|false
	 */
	public static function update( $id, $data ) {
		global $wpdb;
		$data['updated_at'] = Tables::now();
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- core table write.
		return $wpdb->update( self::table(), $data, array( 'id' => absint( $id ) ) );
	}

	/**
	 * Delete a source AND its citations (a citation without its source is
	 * meaningless).
	 *
	 * @param  int $id Row ID.
	 * @return int|false
	 */
	public static function delete_cascade( $id ) {
		global $wpdb;
		$id  = absint( $id );
		$row = $wpdb->get_row( $wpdb->prepare( 'SELECT gedcom, sourceID FROM %i WHERE id = %d', self::table(), $id ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		if ( ! $row ) {
			return false;
		}
		if ( class_exists( 'AncestorPress\Core\Citations_Table' ) ) {
			Citations_Table::delete_by_source( $row->gedcom, $row->sourceID );
		}
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- core table write.
		return $wpdb->delete( self::table(), array( 'id' => $id ) );
	}

	/**
	 * Delete all sources for a tree.
	 *
	 * @param  string $gedcom Tree identifier.
	 * @return void
	 */
	public static function delete_by_gedcom( $gedcom ) {
		global $wpdb;
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- core table write.
		$wpdb->delete( self::table(), array( 'gedcom' => $gedcom ) );
	}

	/**
	 * Next manual source ID (S-1, S-2... - GEDCOM imports use S-series).
	 *
	 * @param  string $gedcom Tree identifier.
	 * @return string
	 */
	public static function next_manual_id( $gedcom ) {
		global $wpdb;
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- LIKE prefix is a trusted literal.
		$rows = $wpdb->get_col( $wpdb->prepare( 'SELECT sourceID FROM %i WHERE gedcom = %s AND sourceID LIKE %s', self::table(), $gedcom, $wpdb->esc_like( 'S-' ) . '%' ) );
		$max  = 0;
		foreach ( $rows as $sid ) {
			$n = (int) substr( $sid, 2 );
			if ( $n > $max ) {
				$max = $n;
			}
		}
		return 'S-' . ( $max + 1 );
	}
}
